pretzel-2.0n-2/0000755000000000000000000000000010765026553012064 5ustar rootrootpretzel-2.0n-2/contrib/0000755000000000000000000000000006537722453013530 5ustar rootrootpretzel-2.0n-2/contrib/index.list0000644000000000000000000000034506360666247015540 0ustar rootrootthis directory & contributed software for Pretzel huhr & Holger Uhr's enhanced Java Prettyprinter for noweb leew & Lee Wittenbergs first Java Prettyprinter for noweb noweb & more stuff on noweb contributed by Felix Gaertner :-) pretzel-2.0n-2/contrib/leew/0000755000000000000000000000000006367034376014465 5ustar rootrootpretzel-2.0n-2/contrib/leew/totex.icn0000644000000000000000000003433006250521226016310 0ustar rootroot# Copyright 1991 by Norman Ramsey. All rights reserved. # See file COPYRIGHT for more information. procedure main(args) local delay, name text := 1 useitemstab := table() defns := table("") TeXspecials := '\\{}$&#^_ ~%' delay := !args == "-delay" noindex := !args == "-noindex" while inputline := read() do inputline ? { if ="@text " then { text +:= *(line := tab(0)) writes(if \quoting then TeXliteral(line) else if \code then escape(line, '{}\\') else line) } else if ="@nl" & pos(0) then { if /code then {if text = 0 then writes("\\nwdocspar") text := 1} if \quoting then writes("\\nwnewline") if \pendinguses | \pendingprev | \pendingnext then { writes("\\nwstartdeflinemarkup") if \pendinguses then { dumpitems(useitems, "nwusesondefline") } if \pendingprev | \pendingnext then { writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{", \pendingnext | "\\relax", "}") } writes("\\nwenddeflinemarkup") pendinguses := pendingprev := pendingnext := &null } write() } else if ="@begin code " then { code := 1 ; writes("\\nwbegincode{", tab(0), "}") every defitems | useitems := [] notused := &null } else if ="@end code " then { dumpitems(defitems, "nwalsodefined") dumpitems(useitems, "nwused") writes("\\nwnotused{", \notused, "}") every defitems | useitems := [] notused := &null code := &null ; writes("\\nwendcode{}") lastdefnlabel := pendingprev := pendingnext := &null } else if ="@defn " then { writes("\\sublabel{", \lastxreflabel, "}") writes("\\nwmargintag{", label2tag(\lastxreflabel), "}") writes("\\moddef{", convquotes(thischunk := tab(0)), ("~" || label2tag(\lastxrefref)) | "", "}\\", defns[thischunk], "endmoddef") useitems := \useitemstab[thischunk] pendinguses := 1 lastdefnlabel := lastxreflabel every lastxreflabel | lastxrefref := &null defns[thischunk] := "plus" } else if ="@begin docs " then { if \delay & match(0) then &null else {text := 0; writes("\\nwbegindocs{",tab(0),"}")} } else if ="@end docs " then { if \delay & match(0) then { writes("\\nwfilename{", filename, "}"); delay := &null } else writes("\\nwenddocs{}") } else if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)), ("~" || label2tag(\lastxrefref)) | "", "\\RA{}") every lastxreflabel | lastxrefref := &null } else if ="@xref " then { if ="label " then { lastxreflabel := tab(0) } else if ="ref " then { lastxrefref := tab(0) } else if ="begindefs" & pos(0) then { } else if ="defitem " then { put(defitems, tab(0)) } else if ="enddefs" & pos(0) then { } else if ="beginuses" & pos(0) then { useitems := [] } else if ="useitem " then { put(useitems, tab(0)) } else if ="enduses" & pos(0) then { useitemstab[thischunk] := useitems } else if ="notused " then { notused := tab(0) } else if ="nextdef " then { pendingnext := tab(0) } else if ="prevdef " then { pendingprev := tab(0) } else if ="beginchunks" & pos(0) then { } else if ="chunkbegin " then { label := tab(upto(' ')); =" " writes("\\nwixlogsorted{c}{{", convquotes(tab(0)), "}{", label, "}{") } else if ="chunkuse " then { writes("\\nwixu{", tab(0), "}") } else if ="chunkdefn " then { writes("\\nwixd{", tab(0), "}") } else if ="chunkend" & pos(0) then { write("}}%") } else if ="endchunks" & pos(0) then { } else warn_unknown("xref " || tab(upto(' \t') | 0)) } else if ="@index " then { if ="nl" & pos(0) then { write(if \code then "\\eatline" else "%")}else if =("defn "|"localdefn ") then /noindex & { writes("\\nosublabel{", \lastxreflabel, "}") writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{", \lastxrefref, "}") every lastxreflabel | lastxrefref := &null } else if ="use " then /noindex & { if /code then { writes("\\protect\\nosublabel{", \lastxreflabel, "}") writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{", \lastxrefref, "}") } every lastxreflabel | lastxrefref := &null } else if ="begindefs" & pos(0) then /noindex & { dumpitems(defitems, "nwalsodefined") dumpitems(useitems, "nwused") writes("\\nwnotused{", \notused, "}") every defitems | useitems := [] notused := &null writes("\\nwidentdefs{") } else if ="isused " then /noindex & { "handled by latex" } else if ="defitem " then /noindex & { i := tab(0); writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}") } else if ="enddefs" & pos(0) then /noindex & { writes("}") } else if ="beginuses" & pos(0) then /noindex & { dumpitems(defitems, "nwalsodefined") dumpitems(useitems, "nwused") writes("\\nwnotused{", \notused, "}") every defitems | useitems := [] notused := &null writes("\\nwidentuses{"); ulist := [] } else if ="isdefined " then /noindex & { "latex finds the definitions" } else if ="useitem " then /noindex & { i := tab(0); writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}") put(ulist, i); } else if ="enduses" & pos(0) then /noindex & { writes("}"); every i := !ulist do writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}") } else if ="beginindex" & pos(0) then /noindex & { } else if ="entrybegin " then /noindex & { label := tab(upto(' ')); =" "; name := tab(0) write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name), "}}{", indexlabel(name), "}}%") } else if ="entryuse " then /noindex & { "handled by latex" } else if ="entrydefn " then /noindex & { "handled by latex" } else if ="entryend" & pos(0) then /noindex & { } else if ="endindex" & pos(0) then /noindex & { } else warn_unknown("index " || tab(upto(' \t') | 0)) } else if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\Tt{}") } else if ="@endquote" & pos(0) then { quoting := &null ; writes("}") } else if ="@file " then { filename := tab(0); every lastxreflabel | lastxrefref := &null \delay | writes("\\nwfilename{", filename, "}") } else if ="@literal " then { writes(tab(0)) } else if ="@header latex " then { writes("\\documentstyle[noweb]{article}\\pagestyle{noweb}\\noweboptions{", tab(0), "}\\begin{document}") } else if ="@header tex " then { writes("\\input nwmac ") } else if ="@trailer latex" & pos(0) then { write("\\end{document}") } else if ="@trailer tex" & pos(0) then { write("\\bye") } else if ="@" then # follows last else warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1))) else write(&errout, "Botched line in noweb pipeline: ", tab(0)) } write() end procedure label2tag(label) return "{\\nwtagstyle{}\\subpageref{" || label || "}}" end procedure dumpitems(items, cs) if *\items > 0 then { writes("\\", cs, "{") every writes("\\\\{", !items, "}") writes("}") return } else fail end procedure escape(line, chars, prefix) /prefix := "\\" line ? { s := "" while s ||:= tab(upto(chars)) do s ||:= prefix || move(1) return s || tab(0) } end global TeXspecials procedure TeXliteral(arg) static nospace, code initial { codes := ["\\", "nwbackslash", "{", "nwlbrace", "}", "nwrbrace", "$", "$", "&", "&", "#", "#", "^", "char94", "_", "_", "%", "%", "~", "char126"] code := table() while (c := get(codes), n := get(codes)) do code[c] := string(n) if c := !TeXspecials & c ~== " " & not member(code, c) then stop("internal error, character-code mismatch, report a bug!") } s := "" arg ? { while s ||:= tab(upto(TeXspecials)) do { c := move(1) if member(code, c) then s ||:= "{\\" || code[c] || "}" else s ||:= "\\" || c } return s || tab(0) } end procedure convquotes(s) r := "" s ? { while r ||:= tab(find("[[")) do { ="[[" | stop("impossible missing [[") r ||:= "\\code{}" || TeXliteral(tab(find("]]"))) r ||:= tab(many(']')-2) ="]]" | stop("impossible missing ]]") r ||:= "\\edoc{}" } return r || tab(0) } end procedure warn_unknown(tag) static warned initial warned := set() if not member(warned, tag) then { write(&errout, "Warning: unrecognized escape @", tag, tab(0)) insert(warned, tag) } return end procedure indexlabel(ident) static badset, trans initial { trans := table() trans[" "] := "sp" # space trans["#"] := "has" # hash trans["$"] := "do" # dollar trans["%"] := "pe" # percent trans["&"] := "am" # ampersand trans[","] := "com" # commad trans[":"] := "col" # colon trans["\\"] := "bs" # backslash trans["^"] := "hat" # hat trans["_"] := "un" # underscore trans["{"] := "lb" # left brace trans["}"] := "rb" # right brace trans["~"] := "ti" # tilde badset := '' every badset ++:= key(trans) } ident ? { s := "" while s ||:= tab(upto(badset)) do s ||:= ":" || trans[move(1)] return s || tab(0) } end pretzel-2.0n-2/contrib/leew/totex.nw0000644000000000000000000004057506240700325016171 0ustar rootroot\section{Converting {\tt noweb} markup to {\TeX} markup (Icon version)} The copyright applies both to the {\tt noweb} source and to the generated shell script. <>= # Copyright 1991 by Norman Ramsey. All rights reserved. # See file COPYRIGHT for more information. @ Here's the organization of the source: <<*>>= <> procedure main(args) local delay, name <> delay := !args == "-delay" noindex := !args == "-noindex" while inputline := read() do inputline ? { <> } write() end @ The markup carefully adds no newlines not already present in the input, so that the line numbers of the {\TeX} file will be the same as the numbers of the corresponding {\tt noweb} file. The variables are: \begin{description} \item[\tt code] Nonnull if converting a code chunk. \item[\tt quoting] Nonnull if quoting code in documentation. \item[\tt text] Number of characters written since start of documentation chunk. \end{description} [[text]] is used to write [[\nwdocspar]] if a newline appears at the beginning of a documentation chunk without any intervening text. This subtle trick preserves new-paragraph semantics without requiring the insertion of a blank line that would throw off the line count. The special control sequences makes a page break at that spot especially likely, so that small documentation chunks will appear on the some page as the code chunks they precede. <>= text := 1 @ %def text Ordering helps improve speed, so I write things in a funny order. This whole code is a giant [[if ... then ... else if ...]]. <>= <<@text>> <<@nl>> <> <<@defn>> <> <<@use>> <<@xref>> <<@index>> <> if ="@" then # follows last else warn_unknown(1(tab(upto(' ')|0), pos(0) | move(1))) else write(&errout, "Botched line in noweb pipeline: ", tab(0)) @ \subsection{Basic text and chunk boundaries} <>= if ="@begin code " then { code := 1 ; writes("\\nwbegincode{", tab(0), "}") <> } else if ="@end code " then { <> code := &null ; writes("\\nwendcode{}") lastdefnlabel := pendingprev := pendingnext := &null } else <>= if ="@begin docs " then { if \delay & match(0) then <> else {text := 0; writes("\\nwbegindocs{",tab(0),"}")} } else if ="@end docs " then { if \delay & match(0) then <> else writes("\\nwenddocs{}") } else <<@text>>= if ="@text " then { text +:= *(line := tab(0)) writes(if \quoting then TeXliteral(line) else if \code then escape(line, '{}\\') else line) } else <<@nl>>= if ="@nl" & pos(0) then { if /code then {<>} if \quoting then writes("\\nwnewline") <> write() } else @ Delaying markup is handled by special patterns for the first document chunk. Because several {\tt noweb} files can be marked up at once, there can be several document chunks numbered 0. The later ones are given no special treatment by the simple expedient of turning [[delay]] off after the first one. <>= &null <>= { writes("\\nwfilename{", filename, "}"); delay := &null } @ <>= if text = 0 then writes("\\nwdocspar") text := 1 @ \subsection{Chunk definitions and uses, with possible cross-reference} Here we start to see the cross-reference markup, driven by [[lastxreflabel]] and [[lastxrefref]]. <<@defn>>= if ="@defn " then { writes("\\sublabel{", \lastxreflabel, "}") writes("\\nwmargintag{", label2tag(\lastxreflabel), "}") writes("\\moddef{", convquotes(thischunk := tab(0)), ("~" || label2tag(\lastxrefref)) | "", "}\\", defns[thischunk], "endmoddef") useitems := \useitemstab[thischunk] pendinguses := 1 lastdefnlabel := lastxreflabel <> defns[thischunk] := "plus" } else @ [[useitemstab]] enables us to show uses even on later instances of a chunk, although the index filter only provides uses with the first chunk. <>= useitemstab := table() <<@use>>= if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)), ("~" || label2tag(\lastxrefref)) | "", "\\RA{}") <> } else <<*>>= procedure label2tag(label) return "{\\nwtagstyle{}\\subpageref{" || label || "}}" end @ [[defns]] serves only to give the proper distinction between [[\endmoddef]] and [[\plusendmoddef]]. <>= defns := table("") @ \subsection{Quoting, headers, trailers, \& miscellany} <>= if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\Tt{}") } else if ="@endquote" & pos(0) then { quoting := &null ; writes("}") } else if ="@file " then { filename := tab(0); <> \delay | writes("\\nwfilename{", filename, "}") } else if ="@literal " then { writes(tab(0)) } else if ="@header latex " then { <> } else if ="@header tex " then { writes("\\input nwmac ") } else if ="@trailer latex" & pos(0) then { write("\\end{document}") } else if ="@trailer tex" & pos(0) then { write("\\bye") } else <>= writes("\\documentstyle[noweb]{article}\\pagestyle{noweb}\\noweboptions{", tab(0), "}\\begin{document}") @ \subsection{Cross-reference and index support} \subsubsection{Chunk cross-reference} We begin with basic cross-reference [[@xref label]] and [[@xref ref]], then show the chunk cross-reference that comes at the end of a code chunk. The {\LaTeX} back end ignores [[@xref nextdef]] and [[@xref prevdef]]. <<@xref>>= if ="@xref " then { <<@xref tests>> <> } else <>= every defitems | useitems := [] notused := &null @ By resetting the cross-reference info after dumping, we make it possible to dump both before index stuff and before end of chunk, without having to do any checking. <>= dumpitems(defitems, "nwalsodefined") dumpitems(useitems, "nwused") writes("\\nwnotused{", \notused, "}") <> <<@xref tests>>= if ="label " then { lastxreflabel := tab(0) } else if ="ref " then { lastxrefref := tab(0) } else if ="begindefs" & pos(0) then { } else if ="defitem " then { put(defitems, tab(0)) } else if ="enddefs" & pos(0) then { } else if ="beginuses" & pos(0) then { useitems := [] } else if ="useitem " then { put(useitems, tab(0)) } else if ="enduses" & pos(0) then { useitemstab[thischunk] := useitems } else if ="notused " then { notused := tab(0) } else if ="nextdef " then { pendingnext := tab(0) } else if ="prevdef " then { pendingprev := tab(0) } else <>= if \pendinguses | \pendingprev | \pendingnext then { writes("\\nwstartdeflinemarkup") <> writes("\\nwenddeflinemarkup") pendinguses := pendingprev := pendingnext := &null } <>= if \pendinguses then { dumpitems(useitems, "nwusesondefline") } if \pendingprev | \pendingnext then { writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{", \pendingnext | "\\relax", "}") } <>= every lastxreflabel | lastxrefref := &null <>= warn_unknown("xref " || tab(upto(' \t') | 0)) <<*>>= procedure dumpitems(items, cs) if *\items > 0 then { writes("\\", cs, "{") every writes("\\\\{", !items, "}") writes("}") return } else fail end @ \subsubsection{Identifier cross-reference, i.e.\ index} <<@index>>= if ="@index " then { <<@index tests>> <> } else <>= warn_unknown("index " || tab(upto(' \t') | 0)) @ This first round of stuff just handles the basics: definitions, uses, and newlines. Unless it's OK to show the index (by \LA{}SI\RA), we handle nothing but \hbox{[[@index nl]]}. <<@index tests>>= if ="nl" & pos(0) then { write(if \code then "\\eatline" else "%")}else if =("defn "|"localdefn ") then <> { <> } else if ="use " then <> { <> } else <>= /noindex & @ Nothing is involved in handling definitions and uses unless there are cross-reference labels pending. An index definition or use has its own [[@xref label]] only if it's in documentation; if it's in code, we use the anchor label of the definition. (You don't have to know that to understand what happens here, but I thought you might like to.) <>= writes("\\nosublabel{", \lastxreflabel, "}") writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{", \lastxrefref, "}") <> @ The {\LaTeX} back end ignores uses in code; they get bundled up by a previous filter (the cross-referencer) and handled elsewhere. <>= if /code then { writes("\\protect\\nosublabel{", \lastxreflabel, "}") writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{", \lastxrefref, "}") } <> @ Here's the local identifier cross-reference that appears at the end of a code chunk. We guard everything with \LA{}SI\RA, as before. <<@index tests>>= if ="begindefs" & pos(0) then <> { <> writes("\\nwidentdefs{") } else if ="isused " then <> { "handled by latex" } else if ="defitem " then <> { i := tab(0); <> } else if ="enddefs" & pos(0) then <> { writes("}") } else if ="beginuses" & pos(0) then <> { <> writes("\\nwidentuses{"); ulist := [] } else if ="isdefined " then <> { "latex finds the definitions" } else if ="useitem " then <> { i := tab(0); <> put(ulist, i); } else if ="enduses" & pos(0) then <> { writes("}"); <> } else <>= writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}") <>= every i := !ulist do writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}") @ \subsubsection{The list of chunks and the index} The treatments of the list of chunks and the index are similar. Both use [[\nwixlogsorted]], which writes magic goo into the {\tt .aux} file. The real cross-referencing is done by the underlying {\LaTeX} code. <<@xref tests>>= if ="beginchunks" & pos(0) then { } else if ="chunkbegin " then { label := tab(upto(' ')); =" " writes("\\nwixlogsorted{c}{{", convquotes(tab(0)), "}{", label, "}{") } else if ="chunkuse " then { writes("\\nwixu{", tab(0), "}") } else if ="chunkdefn " then { writes("\\nwixd{", tab(0), "}") } else if ="chunkend" & pos(0) then { write("}}%") } else if ="endchunks" & pos(0) then { } else <<@index tests>>= if ="beginindex" & pos(0) then <> { } else if ="entrybegin " then <> { label := tab(upto(' ')); =" "; name := tab(0) write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name), "}}{", indexlabel(name), "}}%") } else if ="entryuse " then <> { "handled by latex" } else if ="entrydefn " then <> { "handled by latex" } else if ="entryend" & pos(0) then <> { } else if ="endindex" & pos(0) then <> { } else @ \subsection{Utility procedures} <<*>>= procedure escape(line, chars, prefix) /prefix := "\\" line ? { s := "" while s ||:= tab(upto(chars)) do s ||:= prefix || move(1) return s || tab(0) } end <<*>>= global TeXspecials <>= TeXspecials := '\\{}$&#^_ ~%' @ I can't use [[\\char`\%]] and similar sequences with latex2e, because [[`]] is an active character that suppresses ligatures. So I got TeX to print out the actual character codes for me. This string ([['\\{}$&#^_ ~%']]) should serve as a test. Unfortunately, the character codes for these characters are not the same across fonts. While this is not a problem when everything is in a typewriter font, it can cause major strangenesses when another font is used (Icon, for example, is often typeset in a sans-serif font). Codes for `[[$]]', `[[&]]', `[[#]]', `[[^]]', `[[_]]', `[[~]]' and `[[%]]' use font-independent macros. Since there is no font-independent way to typeset `[[\]]', `[[{]]' and `[[}]]',\footnote{Although both plain \TeX\ and \LaTeX\ provide `[[\{]]' and `[[\}]], plain \TeX\ only allows their use in math mode.} we generate special macros defined in \verb"noweb.sty" and \verb"nwmac.tex". The default definitions are geared to typewriter fonts, but they can be redefined as necessary. <<*>>= procedure TeXliteral(arg) static nospace, code initial { codes := ["\\", "nwbackslash", "{", "nwlbrace", "}", "nwrbrace", "$", "$", "&", "&", "#", "#", "^", "char94", "_", "_", "%", "%", "~", "char126"] code := table() while (c := get(codes), n := get(codes)) do code[c] := string(n) if c := !TeXspecials & c ~== " " & not member(code, c) then stop("internal error, character-code mismatch, report a bug!") } s := "" arg ? { while s ||:= tab(upto(TeXspecials)) do { c := move(1) if member(code, c) then s ||:= "{\\" || code[c] || "}" else s ||:= "\\" || c } return s || tab(0) } end @ A special function is used to implement {\tt noweb}'s quoting convention within chunk names. <<*>>= procedure convquotes(s) r := "" s ? { while r ||:= tab(find("[[")) do { ="[[" | stop("impossible missing [[") r ||:= "\\code{}" || TeXliteral(tab(find("]]"))) r ||:= tab(many(']')-2) ="]]" | stop("impossible missing ]]") r ||:= "\\edoc{}" } return r || tab(0) } end <<*>>= procedure warn_unknown(tag) static warned initial warned := set() if not member(warned, tag) then { write(&errout, "Warning: unrecognized escape @", tag, tab(0)) insert(warned, tag) } return end @ This gets special characters out of the labels used by identifiers. <<*>>= procedure indexlabel(ident) static badset, trans initial { <> badset := '' every badset ++:= key(trans) } ident ? { s := "" while s ||:= tab(upto(badset)) do s ||:= ":" || trans[move(1)] return s || tab(0) } end <>= trans := table() trans[" "] := "sp" # space trans["#"] := "has" # hash trans["$"] := "do" # dollar trans["%"] := "pe" # percent trans["&"] := "am" # ampersand trans[","] := "com" # commad trans[":"] := "col" # colon trans["\\"] := "bs" # backslash trans["^"] := "hat" # hat trans["_"] := "un" # underscore trans["{"] := "lb" # left brace trans["}"] := "rb" # right brace trans["~"] := "ti" # tilde @ %def indexlabel pretzel-2.0n-2/contrib/leew/support.nw0000644000000000000000000013541406240700325016537 0ustar rootroot\documentstyle[noweb,twoside]{article} \pagestyle{noweb} \noweboptions{longchunks,smallcode} \title{{\TeX} support for {\tt noweb}} \author{Norman Ramsey} \newcommand{\stylehook}{\marginpar{\raggedright\sl Style hook}} \begin{document} \maketitle \tableofcontents @ This document describes the {\TeX} code that supports {\tt noweave} and {\tt noweb}. Those interested in customizing their output should focus on Section~\ref{section:sty}. Hooks you can easily use (apart from those provided by [[\noweboptions]]) are indicated by marginal notes. This file contains both plain {\TeX} and {\LaTeX} support: <>= % nwmac.tex -- plain TeX support for noweb % DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead. <>= % noweb.sty -- LaTeX support for noweb % DON'T read or edit this file! Use ...noweb-source/tex/support.nw instead. @ \section{Basic {\TeX} support for {\tt noweb}} This basic code is used for both {\TeX} and {\LaTeX}. The first step is to define [[\codehsize]], which is the width in which code is set, and [[\codemargin]], which is the amount by which it is indented.\stylehook <>= % make \hsize in code sufficient for 88 columns \setbox0=\hbox{\tt m} \newdimen\codehsize \codehsize=91\wd0 % 88 columns wasn't enough; I don't know why \newdimen\codemargin \codemargin=0pt @ %def \codehsize \codemargin [[\defspace]] is the space we would like on the right of navigational info that appears on definition lines, so that it lines up with the text above and below. <>= \newdimen\nwdefspace \nwdefspace=\codehsize \advance\nwdefspace by -\textwidth\relax @ Most code is set in an environment in which [[\setupcode]] has been executed. In this environment, only [[\]], [[{]], and [[}]] have their usual categories; every other character represents itself. Appropriate [[\chardef]]s ensure that the special characters can be escaped with a backslash. <>= \chardef\other=12 \def\setupcode{% \chardef\\=`\\ \chardef\{=`\{ \chardef\}=`\} \catcode`\$=\other \catcode`\&=\other \catcode`\#=\other \catcode`\%=\other \catcode`\~=\other \catcode`\_=\other \catcode`\^=\other \obeyspaces\Tt } \let\nwlbrace=\{ \let\nwrbrace=\} @ %def \setupcode [[\eatline]] is used to consume newlines that should be ignored, for example, the newlines at the end of [[@ %def ]]{\em identifiers} lines. I can't remember what [[\startline]] or [[\newlines]] are for; I don't think {\tt noweave} ever emits them. <>= {\catcode`\^^M=\active % make CR an active character \gdef\newlines{\catcode`\^^M=\active % make CR an active character \def^^M{\par\startline}}% \gdef\eatline#1^^M{\relax}% } %%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write \def\startline{\noindent\hskip\parindent\ignorespaces} \def\nwnewline{\ifvmode\else\hfil\break\fi} @ %def \startline \eatline \nwnewline Within a code environment, it may be necessary to restore the category codes in order to set a module (chunk) name. <>= {\obeyspaces\global\let =\ } % from texbook, p 381 \def\setupmodname{% \catcode`\$=3 \catcode`\&=4 \catcode`\#=6 \catcode`\%=14 \catcode`\~=13 \catcode`\_=8 \catcode`\^=7 \catcode`\ =10 \catcode`\^^M=5 \let\{\nwlbrace \let\}\nwrbrace \Rm} @ %def \setupmodname @ \sublabel{ref:fred} {\tt noweave} brackets uses of chunk names with [[\LA]] and [[\RA]], which handle the angle brackets, font, and environment. As it stands, chunk names can be broken across lines (or pages). This could result in unnecessary page breaks in code (c.f.~p.~\pageref{sec:pagebreaking}). [[\let\\maybehbox=\mbox]] to \stylehook avoid breaking them (or to make them work in math mode); this is done in code chunks, but could be done in general. <>= \def\LA{\begingroup\maybehbox\bgroup\setupmodname\It$\langle$} \def\RA{\/$\rangle$\egroup\endgroup} \def\code{\leavevmode\begingroup\setupcode\newlines} \def\edoc{\endgroup} \let\maybehbox\relax @ %def \LA \RA \maybehbox [[\equivbox]] and [[\plusequivbox]] are used to set the ``\unhcopy\equivbox'' and ``\unhcopy\plusequivbox'' that open a chunk definition or its continuation. {\tt noweave} brackets definitions of chunk names with [[\moddef]] and either [[\endmoddef]] or [[\plusendmoddef]]. <>= \newbox\equivbox \setbox\equivbox=\hbox{$\equiv$} \newbox\plusequivbox \setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$} % \moddef can't have an argument because there might be \code...\edoc \def\moddef{\leavevmode\kern-\codemargin\LA} \def\endmoddef{\RA\ifmmode\equiv\else\unhcopy\equivbox\fi \nobreak\hfill\nobreak} \def\plusendmoddef{\RA\ifmmode\mathord{+}\mathord{\equiv}\else\unhcopy\plusequivbox\fi \nobreak\hfill\nobreak} @ %def \equivbox \plusequivbox \moddef \endmoddef \plusendmoddef @ Within a code environment, margin tags might be used to mark sub-page numbers in the margins, separated by [[\nwmarginglue]].\stylehook The interaction with [[\moddef]] involves tricky kerning. The tag itself is displayed using [[\nwthemargintag]] <>= \def\nwopt@nomargintag{\let\nwmargintag=\@gobble} \def\nwopt@margintag{% \def\nwmargintag##1{\leavevmode\llap{##1\kern\nwmarginglue\kern\codemargin}}} \def\nwopt@margintag{% \def\nwmargintag##1{\leavevmode\kern-\codemargin\nwthemargintag{##1}\kern\codemargin}} \def\nwthemargintag#1{\llap{#1\kern\nwmarginglue}} \nwopt@margintag \newdimen\nwmarginglue \nwmarginglue=0.3in @ %def \nwmargintag margintag nomargintag \nwmarginglue \iffalse <>= .TP .B margintag Put the sub-page number (tag) of each code-chunk definition in the left margin. (Default) .TP .B nomargintag Don't use margin tags. @ \fi [[\nwtagstyle]] determines the style in which tags are displayed.\stylehook <>= \def\nwtagstyle{\footnotesize\Rm} @ <>= \def\chunklist{% \errhelp{I changed \chunklist to \nowebchunks. I'll try to avoid such incompatible changes in the future.}% \errmessage{Use \string\nowebchunks\space instead of \string\chunklist}} \def\nowebchunks{\message{}} \def\nowebindex{\message{}} @ %def \chunklist \nowebchunks \nowebindex @ We have to be careful with font-changing in the presence of different font-selection schemes. In the \LaTeX{} New Font Selection Scheme something like [[\it\tt]] will attempt to use an italic typewriter font. Thus we define new commands like [[\Tt]] which will work with both the Plain and old and new \LaTeX{} schemes. (Note that NFSS will be standard in the next version of \LaTeX.) A problem with these definitions arises with NFSS: in math mode the won't work unless the {\tt oldlfont} backwards-compatibility option is in effect. For the moment, you can get round this by using [[\mbox]]. If you wanted code set in a different font, you could re-define [[\Tt]].\stylehook{} [\LaTeX2e actually behaves like OFSS, but the extra [[\reset@font]] does no harm.] <>= % here is support for the new-style (capitalized) font-changing commands % thanks to Dave Love \ifx\documentstyle\undefined \let\Rm=\rm \let\It=\it \let\Tt=\tt % plain \else\ifx\selectfont\undefined \let\Rm=\rm \let\It=\it \let\Tt=\tt % LaTeX OFSS \else % LaTeX NFSS \def\Rm{\reset@font\rm} \def\It{\reset@font\it} \def\Tt{\reset@font\tt} \def\Bf{\reset@font\bf} \fi\fi \ifx\reset@font\undefined \let\reset@font=\relax \fi @ %def \Rm \Tt \It \Bf @ \clearpage \section{The {\tt noweb} document-style option for {\LaTeX}} \label{section:sty} {\LaTeX} support begins with the kernel shown above. <>= <> @ \subsection{Support for noweb options} <>= \def\noweboptions#1{% \def\@nwoptionlist{#1}% \@for\@nwoption:=\@nwoptionlist\do{% \@ifundefined{nwopt@\@nwoption}{% \@latexerr{There is no such noweb option as '\@nwoption'}\@eha}{% \csname nwopt@\@nwoption\endcsname}}} @ %def \noweboptions \subsection{Adjusting placement of code on the page} {\LaTeX} requires a larger [[\codehsize]] because code is indented by [[\codemargin]].\stylehook <>= \codemargin=10pt \advance\codehsize by \codemargin % make room for indentation of code \advance\nwdefspace by \codemargin % and fix adjustment for def/use @ [[\noweboptions{shift}]] is used to shift the whole page left to make room for the wide code lines. It may be emitted by {\tt noweave -shift}, or it might be given by a user. <>= \def\nwopt@shift{% \dimen@=-0.8in \if@twoside % Values for two-sided printing: \advance\evensidemargin by \dimen@ \else % Values for one-sided printing: \advance\evensidemargin by \dimen@ \advance\oddsidemargin by \dimen@ \fi % \advance \marginparwidth -\dimen@ } \let\nwopt@noshift\@empty @ %def shift noshift \iffalse <>= .TP .B shift Shift text to the left so that long code lines won't extend off the right-hand side of the page. @ \fi \subsection{Page-breaking strategy}\label{sec:pagebreaking} We want to insert penalties aiming for: \begin{enumerate} \item No page breaks in the middle of a code chunk unless necessary to avoid an overfull vbox; \item Documentation immediately preceding a code chunk should appear on the same page as that code chunk unless doing so would violate rule 1. \end{enumerate} [[\filbreak]] is useful for this sort of thing (see {\em The \TeX book\/}) and is used to encourage breaks at the right places between chunks. Appropriate penalties are inserted elsewhere, between code lines in particular. \subsection{Environments for setting code} [[\nwbegincode]] and [[\nwendcode]] are used by {\tt noweave} to bracket code chunks. The [[webcode]] environment is intended for users who want to paste {\tt noweave} output into papers. The definition of [[\nwbegincode]] is based on the verbatim implementation in {\tt verbatim.sty}, which will, presumably be in the next version of \LaTeX\@. One thing it does differently, apart from the catcode changes is setting [[\linewidth]]; this will avoid some overfull hboxen when the code lines are too long, but the lines won't be broken anyhow (even within chunk names because of the [[\maybehbox]] definition). <>= \def\nwbegincode#1{% \begingroup <<[[\nwbegincode]] separation and penalties>> \@begincode } \def\nwendcode{\endtrivlist \endgroup \filbreak} % keeps code on 1 page \newenvironment{webcode}{% \@begincode }{% \endtrivlist} @ %def \nwbegincode \nwendcode webcode @ This is just common code between [[\nwbegincode]] and [[webcode]]. <>= \def\@begincode{% <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>> \linewidth\codehsize <<[[\obeylines]] setup>> <> \nowebsize \setupcode \let\maybehbox\mbox } @ %def \@begincode @ \iffalse <>= .TP .B smallcode Set code in .I LaTeX .B "\\\\small" font instead of .B "\\\\normalsize." @ \fi @ [[\nowebsize]] governs the size at which code is set; users who want to minimize code can [[\let\nowebsize=\small]]. Slitex users should try \begin{quote} [[\def\nowebsize{\normalsize\baselineskip=20pt \parskip=5pt }]] \end{quote} to avoid code lines that are too far apart. [[\nwcodetopsep]] is the glue placed before code chunks.\stylehook <>= \newskip\nwcodetopsep \nwcodetopsep = 3pt plus 1.2pt minus 1pt \let\nowebsize=\normalsize \def\nwopt@smallcode{\let\nowebsize=\small} @ %def \nwcodetopsep \nowebsize smallcode @ Maybe the penalties ought to be parameters\dots <<[[\nwbegincode]] separation and penalties>>= \topsep \nwcodetopsep \@beginparpenalty \@highpenalty \@endparpenalty -\@highpenalty @ The [[\trivlist]] clich\'e isn't quite a clich\'e because we adjust [[\leftskip]] for indentation by [[\codemargin]] and adjust [[\rightskip]] to allow lines up to [[\codehsize]] long without overfull boxen ($\mbox{[[\codehsize]]}=\mbox{[[\hsize]]}+\mbox{[[\rightskip]]}$). Note that [[\hsize]] isn't altered. <<[[\trivlist]] clich\'e (\`a la {\Tt verbatim})>>= \trivlist \item[]% \leftskip\@totalleftmargin \advance\leftskip\codemargin \rightskip\hsize \advance\rightskip -\codehsize \parskip\z@ \parindent\z@ \parfillskip\@flushglue @ The penalty inserted between verbatim lines would normally be [[\interlinepenalty]], but we want to prohibit breaks there. @ Note the bug lurking somewhere in this code, as reported by Steven Ooms: \begin{quote} I have some lay-out problems in the documentation chunks. When using the (La)TeX commands [[\hline]] or [[\vtop]] the right margin is always extended far beyond the page margin after the first code chunk has been typeset. I'm still looking for the exact cause of it, but to me it seems that LaTeX supposes for those commands that the line width for the documentation chunk is as large as that for code chunks, which isn't true in reality. \end{quote} @ <<[[\obeylines]] setup>>= \@@par \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}% \obeylines @ [[\nwcodepenalty]] is the penalty for breaking between lines in a code chunk. If you set it to 10000, code will never be broken across pages.\stylehook{} I guess this should be settable in [[\noweboptions]]. <>= \newcount\nwcodepenalty \nwcodepenalty=\@highpenalty @ %def \nwcodepenalty The cursing chunk accounts for the addition of a mess of characters to those reset by [[\@noligs]] in \LaTeX2e. <>= \@noligs <> \setupcode \frenchspacing \@vobeyspaces @ We can't make [[`]] ``other,'' because then we'll get ligatures. (Why Don put these ligatures in the [[\tt]] font I wish I knew.) But we'll step on all the others. <>= \ifx\verbatim@nolig@list\undefined\else \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\` \fi <>= \def\nw@makeother#1{\catcode`#1=12 } @ {\tt noweave} uses [[\nwbegindocs{nnn}]] and [[\nwenddocs]] to bracket documentation chunks. If a documentation chunk does not continue the current paragraph, {\tt noweave} inserts [[\nwdocspar]], which uses [[\filbreak]] in an attempt to keep the documentation chunk on the same page as the code chunk that follows it. (The code chunk will have another [[\filbreak]] after it---see [[\nwbegincode]].) [[\nwbegindocs]] doesn't start a new paragraph if the previous chunk didn't end one, i.e.\ didn't enter vmode; if it does start a new one, it's only indented by the use of [[\nwdocspar]]. <>= \def\nwbegindocs#1{\ifvmode\noindent\fi} \let\nwenddocs=\relax \let\nwdocspar=\filbreak @ %def \nwbegindocs \nwdocspar \nwenddocs The page-breaking strategy implies ragged bottom pages, so we should turn it on in general (this is relevant for the {\tt report} style): <>= \raggedbottom <>= \def\nwdocspar{\par\semifilbreak} @ {\tt noweave} doesn't bracket quoted code with [[\code]] and [[\edoc]] any more. It probably should do something nifty, just to make {\TeX} hackers happy, but it doesn't. <>= \def\code{\leavevmode\begingroup\setupcode\@vobeyspaces\obeylines} \let\edoc=\endgroup @ \subsection{The {\tt noweb} page style} Headers contain file name, date, and page number. {\tt noweave} emits [[\nwfilename{]]{\em name}[[}]] for each new file. In the {\tt noweb} page style, new files cause page breaks; otherwise they are ignored. <>= \newdimen\@original@textwidth \def\ps@noweb{% \@original@textwidth=\textwidth \let\@mkboth\@gobbletwo \def\@oddfoot{}\def\@evenfoot{}% No feet. \if@twoside % If two-sided printing. \def\@evenhead{\hbox to \@original@textwidth{% \Rm \thepage\qquad{\Tt\leftmark}\hfil\today}}% Left heading. \def\@oddhead{\hbox to \@original@textwidth{% \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading. \else % If one-sided printing. \def\@oddhead{\hbox to \@original@textwidth{% \Rm \today\hfil{\Tt\leftmark}\qquad\thepage}}% Right heading. \let\@evenhead\@oddhead \fi \let\chaptermark\@gobble \let\sectionmark\@gobble \let\subsectionmark\@gobble \let\subsubsectionmark\@gobble \let\paragraphmark\@gobble \let\subparagraphmark\@gobble \def\nwfilename{\begingroup\let\do\@makeother\dospecials \catcode`\{=1 \catcode`\}=2 \nw@filename} \def\nw@filename##1{\endgroup\markboth{##1}{##1}\let\nw@filename=\nw@laterfilename}% } \def\nw@laterfilename#1{\endgroup\clearpage \markboth{#1}{#1}} \let\nwfilename=\@gobble @ %def \@original@textwidth \ps@noweb \nwfilename @ \subsection{Chunk cross-reference} [[\nwalsodefined]], [[\nwused]], and [[\nwnotused]] are emitted by the {\tt noweb} cross-referencers. (What arguments?) If unused chunks are output chunks, a filter can slip in [[\let\nwnotused\nwoutput]]. The style uses [[\nwcodecomment]] for all annotations that follow code chunks. Fiddling with it can change the appearance of the output. Note that [[\nwcodecomment]] is used after [[\nwbegincode]], with [[\obeylines]] in efect. Since linebreaking can occur here, we need to change the [[\interlinepenalty]]. A little vertical space ([[\nwcodecommentsep]]\stylehook) appears before the first comment. We firkled with [[\rightskip]] in [[\nwbegincode]] above; now we want to reset it so that paragraphs are the normal width ([[\textwidth]], possibly less [[\codemargin]]) and set ragged right. This is done as usuall by making [[\rightskip]] naturally zero but stretchable. <>= \def\nwcodecomment#1{\@@par\penalty\nwcodepenalty <>% \hspace{-\codemargin}{% \rightskip=0pt plus1in \interlinepenalty\nwcodepenalty \let\\\relax\footnotesize\Rm #1\@@par\penalty\nwcodepenalty}} @ %def \nwcodecomment This stuff is used at the end of a chunk. <>= \def\@nwalsodefined#1{\nwcodecomment{This definition is continued \nwpageprep\ \@pagesl{#1}.}} \def\@nwused#1{\nwcodecomment{This code is used \nwpageprep\ \@pagesl{#1}.}} \def\@nwnotused#1{\nwcodecomment{Root chunk (not used in this document).}} \def\nwoutput#1{\nwcodecomment{This code is written to file {\Tt \@stripstar#1*\stripped}.}} \def\@stripstar#1*#2\stripped{#1} @ %def \nwalsodefined \nwused \nwnotused \nwoutput <>= \if@firstnwcodecomment \vskip\nwcodecommentsep\penalty\nwcodepenalty\@firstnwcodecommentfalse \fi @ This stuff on the definition line. Note the hooks\stylehook{} for pointer styles. <>= \newcommand{\nwprevdefptr}[1]{% \mbox{$\mathord{\triangleleft}\,\mathord{\mbox{\subpageref{#1}}}$}} \newcommand{\nwnextdefptr}[1]{% \mbox{$\mathord{\mbox{\subpageref{#1}}}\,\mathord{\triangleright}$}} \newcommand{\@nwprevnextdefs}[2]{% {\nwtagstyle \ifx\relax#1\else ~~\nwprevdefptr{#1}\fi \ifx\relax#2\else ~~\nwnextdefptr{#2}\fi}} \newcommand{\@nwusesondefline}[1]{{\nwtagstyle~~(\@pagenumsl{#1})}} \newcommand{\@nwstartdeflinemarkup}{\nobreak\hskip 1.5em plus 1fill\nobreak} \newcommand{\@nwenddeflinemarkup}{\nobreak\hskip \nwdefspace minus\nwdefspace\nobreak} @ And here are the options we use to choose one or the other. <>= \def\nwopt@longxref{% \let\nwalsodefined\@nwalsodefined \let\nwused\@nwused \let\nwnotused\@nwnotused \let\nwprevnextdefs\@gobbletwo \let\nwusesondefline\@gobble \let\nwstartdeflinemarkup\relax \let\nwenddeflinemarkup\relax } \def\nwopt@shortxref{% \let\nwalsodefined\@gobble \let\nwused\@gobble \let\nwnotused\@gobble \let\nwprevnextdefs\@nwprevnextdefs \let\nwusesondefline\@nwusesondefline \let\nwstartdeflinemarkup\@nwstartdeflinemarkup \let\nwenddeflinemarkup\@nwenddeflinemarkup } \nwopt@shortxref % to hell with backward compatibility! @ \iffalse <>= .TP .B longxref, shortxref Use either long, Knuth-style chunk cross-reference, or short, Hanson-style chunk cross-reference. The former uses small paragraphs after the chunk; the latter uses symbols on the definition line. Defaults to .B shortxref. @ \fi <>= \newskip\nwcodecommentsep \nwcodecommentsep=3pt plus 1pt minus 1pt \newif\if@firstnwcodecomment\@firstnwcodecommenttrue @ \subsection{Page ranges} The goal is to combine sub-page numbers in a way that makes sense. Multiple sub-pages of one page become that page, and individual pages are combined into ranges. (A range may be only one page.) <>= \newcount\@nwlopage\newcount\@nwhipage % range lo..hi-1 \newcount\@nwlosub % subpage of lo \newcount\@nwhisub % subpage of hi \def\@nwfirstpage#1#2{% subpage page \@nwlopage=#2 \@nwlosub=#1 \advance\@nwpagecount by \@ne <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>} \def\@nwnextpage#1#2{% subpage page \ifnum\@nwhipage=#2 \advance\@nwhipage by \@ne \advance\@nwpagecount by \@ne \@nwhisub=#1 \else \ifnum#2<\@nwlopage <>\else \ifnum#2>\@nwhipage <>\else \@nwlosub=0 \@nwhisub=0 \fi\fi\fi } <>= <>\@nwfirstpage{#1}{#2} <<$\mbox{[[\@nwhipage]]} := \mbox{[[\@nwlopage]]}+1$>>= \@nwhipage=\@nwlopage\advance\@nwhipage by \@ne <>= <>% \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa <>= \advance\@nwhipage by \m@ne \ifnum\@nwhipage=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}}% \else \count@=\@nwhipage \advance\count@ by \m@ne \ifnum\count@=\@nwlopage % consecutive pages \edef\@tempa{\noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}% \noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}}% \else <>% \fi \fi <>= \ifnum\@nwlopage<110 <>\else \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100 \ifnum\count@=\@nwlopage <>\else \count@=\@nwlopage \divide\count@ by 100 \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100 \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi \multiply\@nwpagetemp by 100 \advance \@nwhipage by -\@nwpagetemp <>% \else <>% \fi \fi \fi <>= \edef\@tempa{\noexpand\noexpand\noexpand\\{\number\@nwlopage--\number\@nwhipage}} <>= \newcount\@nwpagetemp @ The sequence [[\@pagesl]] makes a range of pages from a list of labels. [[\subpages]] works from a list of [[{{subpage}{page}}]]. <>= \newcount\@nwpagecount \def\@nwfirstpagel#1{% label \@ifundefined{r@#1}{<>}{% \edef\@tempa{\noexpand\@nwfirstpage\subpagepair{#1}}\@tempa}} \def\@nwnextpagel#1{% label \@ifundefined{r@#1}{<>}{% \edef\@tempa{\noexpand\@nwnextpage\subpagepair{#1}}\@tempa}} \def\@pagesl#1{% list of labels \gdef\nw@pages{}\@nwpagecount=0 \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1% <>\let\\=\relax \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}} \def\@pagenumsl#1{% list of labels -- doesn't include word `pages', commas, or `and' \gdef\nw@pages{}\@nwpagecount=0 \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1% <>\def\\{\let\\=~}\nw@pages} \def\subpages#1{% list of {{subpage}{page}} \gdef\nw@pages{}\@nwpagecount=0 \def\\##1{\edef\@tempa{\noexpand\@nwfirstpage##1}\@tempa \def\\####1{\edef\@tempa{\noexpand\@nwnextpage####1}\@tempa}}#1% <>\let\\=\relax \nwpageword\ifnum\@nwpagecount=1 \else s\fi~\commafy{\nw@pages}} \def\@nwaddrange{<>} @ [[\nwpageword]] and [[\nwpageprep]] let you change the wording of the cross-reference information. <>= \def\nwpageword{chunk} % was page \def\nwpageprep{in} % was on <>= <>% \nwix@cons\nw@pages{\\{\bf ??}} @ \subsection{Sub-page references} This is the wonderful code that Dave Love provided to make page references like 7a, 7b, and so on. This code provides a mechanism for defining `page sub-references' using [[\sublabel{foo}]] referenced with [[\subpageref{foo}]]. Sub-references will be numbered like these real examples: \subpageref{ref:foo}, \subpageref{ref:bar}, \subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz} etc.\ unless there is only one on the page, in which case the letter will be dropped like this: \subpageref{ref:fred}. To be able to use [[\subpageref]] we must define the label with [[\sublabel]], used like label. (Using [[\ref]] with a label defined by [[\sublabel]] will produce the sub-reference number, by the way, and [[\pageref]] works as expected.) Note that [[\subpageref]] is robust and [[\ref]] and [[\pageref]] are redefined to be robust also, as they will be in future \LaTeX{} releases. Incidentally, these expand to the relevant text plus [[\null]]---you might want to strip this off, e.g.\ for sorting lists. There are various ways we could attack this task (which is made non-trivial by the well-known asynchrony of (La)\TeX's output routine), but they all must depend on hacks in the [[.aux]] file or a similar one. Joachim Schrod's [[fnpag.sty]] does the same sort of thing differently to this \LaTeX-specific approach. See [[latex.tex]] for enlightenment on the cross-referencing mechanism and the \LaTeX{} internals used below. [DL: The internals change in \LaTeX2e compared with \LaTeX~2.09. The code here still works, though.] @ The [[\subpageref]] macro first does a normal [[\pageref]]. If the reference is actually defined, it then goes on to check whether the control sequence [[2on]]\LA{}{page referenced}\RA{} is defined and sets the [[\ref]] value to get [[a]] etc.\ if so. The magic, of course, is in defining the [[2on]] bit appropriately. [[\subpageref]] also tries to include the right hyperstuff for xhdvi. <>= \newcommand{\subpageref}[1]{% \nwhyperreference{#1}{% \@ifundefined{r@#1}% {\pageref{#1}}% {\@ifundefined{2on\@pageref{#1}}% {\pageref{#1}}% {\expandafter\expandafter\expandafter\nwthepagenum\csname r@#1\endcsname}}}} @ %def \subpageref [[\subpagepair]] produces a [[{subpage}{page}]] pair. <>= \newcommand{\subpagepair}[1]{% % produces {subpage}{page} \@ifundefined{r@#1}% {{0}{0}}% {\@ifundefined{2on\@pageref{#1}}% {{0}{\expandafter\expandafter\expandafter\@cdr\csname r@#1\endcsname\@nil}}% {\@nameuse{r@#1}}}} @ [[\@pageref]] is like [[\pageref]], but it expands to [[\relax]] without a warning if the reference is undefined. <>= \def\@pageref#1{\expandafter\expandafter\expandafter \@cdr\csname r@#1\endcsname\@nil} @ %def \@pageref @ [[\sublabel]] is like the [[\label]] command, except that it writes [[\newsublabel]] onto the [[.aux]] file rather than [[\newlabel]]. For hyperreferencing, all labels must be hypertext anchors, for which we use [[\nwblindhyperanchor]]. <>= \newcommand{\sublabel}[1]{% \nwblindhyperanchor{#1}% \@bsphack\if@filesw {\let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string \newsublabel{#1}{{}{\thepage}}}}% \expandafter}\@tempa \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} @ %def \sublabel [[\nosublabel]] creates a label with a sub-page part of~0. <>= \newcommand{\nosublabel}[1]{% \@bsphack\if@filesw {\let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string \newlabel{#1}{{0}{\thepage}}}}% \expandafter}\@tempa \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} @ %def \sublabel @ [[\newsublabel]] is the macro that does the important work. It is called with the same sort of arguments as [[\newlabel]]: the first argument is the label name and the second is [[{]]\LA ref value[[}{]]page number\RA[[}]]. (Note that the only definition here which needs to be global is the one which is, and that [[\global]] is redefined by [[\enddocument]], which will bite you if you use it\dots) <>= <> @ First we extract the page number into [[\this@page]]. <>= \newcommand{\newsublabel}[2]{% \edef\this@page{\@cdr#2\@nil}% @ %def \newsublabel @ Then we see whether it's changed from the value of [[\last@page]] which was stashed away by the last [[\newsublabel]] (or is [[\relax]] if this is the first one). If the page has changed, we reset the counter [[\sub@page]] telling us how many sub-labels there have been on the page. <>= \ifx\this@page\last@page\else \sub@page=\z@ \fi \edef\last@page{\this@page} \advance\sub@page by \@ne @ If we've had at least two on the page, we define the [[2on]]\LA{}{page no.}\RA{} macro to indicate the fact. <>= \ifnum\sub@page=\tw@ \global\@namedef{2on\this@page}{}% \fi @ Then we write a normal [[\newlabel]] with the sub-reference as the normal reference value in the second argument. <>= \edef\@tempa{\noexpand\newlabel{#1}% {{\number\sub@page}{\this@page}}}% \@tempa} @ We need to define these. <>= \def\last@page{\relax} \newcount\sub@page @ %def \last@page \sub@page @ We use Rainer's new expandable definitions of [[\ref]] and [[\pageref]] to minimise the risk of nasty surprises. <>= % RmS 92/08/14: made \ref and \pageref robust \def\ref#1{\@ifundefined{r@#1}{{\bf ??}<>}% {\expandafter\expandafter\expandafter \@car\csname r@#1\endcsname\@nil\null}} \def\pageref#1{\@ifundefined{r@#1}{{\bf ??}<>}% {\expandafter\expandafter\expandafter \@cdr\csname r@#1\endcsname\@nil\null}} \def\@refpair#1{\@ifundefined{r@#1}{{0}{0}<>}% {\@nameuse{r@#1}}} <>= \@warning{Reference `#1' on page \thepage \space undefined} @ %def \ref \pageref @ Here a a couple of hooks for formatting sub-page numbers, which can be alphbetic, numeric, or omitted.\stylehook <>= \def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\@alph{#1}\fi} \def\@nosubpagenum#1#2{#2} \def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\@arabic{#1}\fi} \def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag} \def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum} \def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum} \nwopt@alphasubpage @ %def \nwthepagenum nosubpage numsubpage alphasubpage \iffalse <>= .TP .B alphasubpage, numsubpage, nosubpage Number chunks by the number of the page on which they appear, followed by an alphabetic (numeric, not used) ``sub-page'' indicator. Defaults to .B alphasubpage. .B nosubpage implies .B nomargintag. @ \fi @ \subsection{{\tt WEB}-like chunk numbering} Here's a righteous hack: we get the effect of WEB-like chunk numbers just by redefining [[\sublabel]] to use a counter instead of the current page number. Since the numbers are all distinct, no sub-page number is ever used. <>= \newcount\nw@chunkcount \nw@chunkcount=\@ne \newcommand{\weblabel}[1]{% \@bsphack\if@filesw {\let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string \newsublabel{#1}{{}{\number\nw@chunkcount}}}}% \expandafter}\@tempa \global\advance\nw@chunkcount by \@ne \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} \def\nwopt@webnumbering{\let\sublabel=\weblabel\def\nwpageword{chunk}\def\nwpageprep{in}} @ %def \weblabel webnumbering \iffalse <>= .TP .B webnumbering Number chunks consecutively, in .I WEB style, instead of using sub-page numbers. @ \fi @ \subsection{Indexing (identifier cross-reference) support} \subsubsection{Tracking definitions and uses} All index definitions and uses are associated with a label defined with [[\sublabel]] or [[\nosublabel]]. Either the label is the [[\sublabel]] of the code chunk in which the definition or use appears, or it is a [[\nosublabel]] appearing in the middle of a documentation chunk. <>= % \nwindexdefn{printable name}{identifying label}{label of chunk} % \nwindexuse{printable name}{identifying label}{label of chunk} \def\nwindexdefn#1#2#3{\@auxix{\protect\nwixd}{#2}{#3}} \def\nwindexuse#1#2#3{\@auxix{\protect\nwixu}{#2}{#3}} \def\@auxix#1#2#3{% {marker}{id label}{subpage label} \@bsphack\if@filesw {\let\nwixd\relax\let\nwixu\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}% \expandafter}\@tempa \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} @ %def \nwindexdefn \nwindexuse \@auxix <>= % \nwixadd{marker}{idlabel}{subpage label} \def\nwixadd#1#2#3{% \@ifundefined{nwixl@#2}% {\global\@namedef{nwixl@#2}{#1{#3}}}% {\expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}}} @ %def \nwixadd @ \subsubsection{Writing lists with commas and ``and''} You get one of \begin{itemize} \item ``$a$'' \item ``$a$ and $b$'' \item ``$a$, $\ldots$, $b$, and $c$'' \end{itemize} Plus [[\\]] is applied to each element of the list. <>= \newcount\@commacount \def\commafy#1{% {\nwix@listcount{#1}\@commacount=\nwix@counter \let\@comma@each=\\% \ifcase\@commacount\let\\=\@comma@each\or\let\\=\@comma@each\or \def\\{\def\\{ and \@comma@each}\@comma@each}\else \def\\{\def\\{, % \advance\@commacount by \m@ne \ifnum\@commacount=1 and~\fi\@comma@each}\@comma@each}\fi #1}} @ %def \@commacount \commafy \subsubsection{New, improved index code} There are two kinds of lists. One kind is a generic list in which elements are preceded by [[\\]]. If the elements are index elements, they are {\em[[{]]printable identifier[[}{]]label[[}]]} pairs. The other kind is a list of sub-page labels, in which each element is preceded by either [[\nwixd]] or [[\nwixu]]. <>= \def\nwix@cons#1#2{% {list}{\marker{element}} {\toks0=\expandafter{#1}\def\@tempa{#2}\toks2=\expandafter{\@tempa}% \xdef#1{\the\toks0 \the\toks2 }}} @ %def \nwix@cons The reference list for an identifier labelled {\em id} is always called [[\nwixl@]]{\em id}. Most applications will work with reference lists by applying [[\\]] either to the defs or to the uses. <>= \def\nwix@uses#1{% {label} \def\nwixu{\\}\let\nwixd\@gobble\@nameuse{nwixl@#1}} \def\nwix@defs#1{% {label} \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}} @ %def \nwix@uses \nwix@defs Some applications count uses to see whether there is any need to display information. <>= \newcount\nwix@counter \def\nwix@listcount#1{% {list with \\} {\count@=0 \def\\##1{\advance\count@ by \@ne }% #1\global\nwix@counter=\count@ }} \def\nwix@usecount#1{\nwix@listcount{\nwix@uses{#1}}} \def\nwix@defcount#1{\nwix@listcount{\nwix@defs{#1}}} @ %def \nwix@listcount \nwix@usecount \nwix@defcount @ \subsubsection{Supporting a mini-index at the end of each chunk} When displaying identifiers used, show the identifier and its definitions. <>= \def\nwix@id@defs#1{% index pair {{\Tt \@car#1\@nil}% \def\\##1{~\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}}} \def\nwidentuses#1{% list of index pairs \nwcodecomment{Uses \let\\=\nwix@id@defs\commafy{#1}.}} @ %def \nwidentuses \nwix@id@defs The definitions section is a bit more complex, because it is omitted if none of the identifiers defined is ever used. <>= \def\nwix@totaluses#1{% list of index pairs {\count@=0 \def\\##1{\nwix@usecount{\@cdr##1\@nil}\advance\count@ by\nwix@counter}% #1\global\nwix@counter\count@ }} \def\nwix@id@uses#1#2{% {ident}{label} \nwix@usecount{#2}\ifnum\nwix@counter>0 {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, used \nwpageprep\ \@pagesl{\nwix@uses{#2}}.}}% \else \ifnw@hideunuseddefs\else {\advance\leftskip by \codemargin \nwcodecomment{{\Tt #1}, never used.}}% \fi \fi} \def\nwidentdefs#1{% list of index pairs \ifnw@hideunuseddefs\nwix@totaluses{#1}\else\nwix@listcount{#1}\fi \ifnum\nwix@counter>0 \nwcodecomment{Defines:}% {\def\\##1{\nwix@id@uses ##1}#1}% \fi} <>= \newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse \def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue} @ \iffalse <>= .TP .B hideunuseddefs Omit defined but unused identifiers from the local identifier cross-reference (Preston Briggs). @ \fi <>= \def\nwopt@noidentxref{% \let\nwidentdefs\@gobble \let\nwidentuses\@gobble} @ \iffalse <>= .TP .B noidentxref Omit the local identifier cross-reference which follows each code chunk. @ \fi \subsubsection{Support for chunk and identifier indices} The index in the back shows absolutely all the pages. <>= \def\nw@underlinedefs{% {list with \nwixd, \nwixu} \let\\=\relax\def\nw@comma{, } \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}% \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}} \def\nw@indexline#1#2{% {\indent {\Tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par}} \newenvironment{thenowebindex}{\parindent=-10pt \parskip=\z@ \advance\leftskip by 10pt \advance\rightskip by 0pt plus1in\par\@afterindenttrue \def\\##1{\nw@indexline##1}}{} @ The information comes from the list [[nwisx@i]]. <>= \def\nowebindex{% \@ifundefined{nwixs@i}% {\@warning{The \string\nowebindex\space is empty}}% {\begin{thenowebindex}\@nameuse{nwixs@i}\end{thenowebindex}}} @ Here's a more efficient version for the external case: <>= \def\nowebindex@external{% {\let\nwixadds@c=\@gobble \def\nwixadds@i##1{\nw@indexline##1}% \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% \begin{thenowebindex}\@input{\jobname.nwi}\end{thenowebindex}}} @ That list ([[nwisx@i]]) is created by calls to [[\nwixlogsorted{i}]]. <>= \def\nwixlogsorted#1#2{% list data \@bsphack\if@filesw \toks0={#2}\immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}} \if@nobreak \ifvmode\nobreak\fi\fi\fi\@esphack} @ [[nwixs@c]] and [[nwixs@i]] are sorted lists of chunks and identifiers, respectively. <>= \def\nwixadds#1#2{% \@ifundefined{nwixs@#1}% {\global\@namedef{nwixs@#1}{\\{#2}}}% {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}} \let\nwixaddsx=\@gobbletwo @ If an external index is used, we need a [[.nwi]] file, [[\nwixadds]] is to be ignored, and we use [[\nwixaddsx]]. <>= \def\nwopt@externalindex{% \ifx\nwixadds\@gobbletwo % already called \else \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo \let\nowebindex=\nowebindex@external \let\nowebchunks=\nowebchunks@external \fi} @ \iffalse <>= .TP .B externalindex Use an index generated with .I noindex(1) (q.v.). @ \fi @ <>= \def\nowebchunks{% \@ifundefined{nwixs@c}% {\@warning{The are no \string\nowebchunks}}% {\begin{thenowebchunks}\@nameuse{nwixs@c}\end{thenowebchunks}}} \def\nowebchunks@external{% {\let\nwixadds@i=\@gobble \def\nwixadds@c##1{\nw@onechunk##1}% \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}}} \@namedef{r@nw@notdef}{{0}{(never defined)}} <>= \def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu} \let\\=\relax\def\nw@comma{, } \def\nwixd##1{\\\underline{\subpageref{##1}}\let\\\nw@comma}% \def\nwixu##1{\\\subpageref{##1}\let\\\nw@comma}} <>= \def\nw@onechunk#1#2#3{% {name}{label of first definition}{list with \nwixd, \nwixu} \@ifundefined{r@#2}{}{% \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA \if@nwlongchunks{~\nw@chunkunderlinedefs#3}\fi\par}} <>= \newenvironment{thenowebchunks}{\vskip3pt \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt \advance\rightskip by 0pt plus10pt \@afterindenttrue \def\\##1{\nw@onechunk##1}}{} <>= \newif\if@nwlongchunks \@nwlongchunksfalse \let\nwopt@longchunks\@nwlongchunkstrue @ \iffalse <>= .TP .B longchunks When expanding .B "\\\\nowebchunks," show page numbers of definitions and uses of each chunk. @ \fi @ \subsection{support for hypertext with {\tt hyper.sty}} Initial support courtesy of Balasubramanian Narasimhan. <>= \newcommand\nwhyperreference[2]{% \@ifundefined{hyperreference}% {#2\global\let\nwhyperreference\@gobble}% {\hyperreference{#1}{#2}\global\def\nwhyperreference\hyperreference}} \newcommand\nwblindhyperanchor[1]{% \@ifundefined{blindhyperanchor}% {\global\let\nwblindhyperanchor\@gobble}% {\blindhyperanchor{#1}\global\def\nwblindhyperanchor\blindhyperanchor}} @ \subsection{Support for Prettyprinting} The following macro can be redefined to allow custom typesetting of identifiers in the index and mini-indices. <>= \let\nwixident=\relax @ %def \nwixident @ The following macros can be redefined to typeset `[[\]]', `[[\]]' and `[[\]]' correctly in non-typewriter fonts. <>= \def\nwbackslash{\char92} \let\nwlbrace=\{ \let\nwrbrace=\} <>= \def\nwbackslash{\char92} \def\nwlbrace{\char123} \def\nwrbrace{\char125} @ \clearpage \section{The {\tt nwmac} macros for use with plain {\TeX}} First we make [[@]] a letter so that we can use `private' macro names. <>= \catcode`\@=11 <>= % scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist \font\twlbf=cmbx10 scaled \magstep1 \font\frtbf=cmbx10 scaled \magstep2 % These fonts don't work with xdvi! \advance\hoffset 0.5 true in \advance\hsize -1.5 true in \newdimen\textsize \textsize=\hsize \def\today{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} @ %def \textsize \today <>= \long\def\ifundefined#1#2#3{% \expandafter\ifx\csname#1\endcsname\relax #2% \else#3% \fi} \ifundefined{myheadline} {\headline={\hbox to \textsize{\tentt\firstmark\hfil\tenrm\today\hbox to 4em{\hss\folio}}\hss}} {\expandafter\headline\expandafter{\myheadline}} \ifundefined{myfootline} {\footline={\hfil}} {\expandafter\footline\expandafter{\myfootline}} @ %def \ifundefined <>= \def\semifilbreak{\vskip0pt plus1.5in\penalty-200\vskip0pt plus -1.5in} \raggedbottom @ %def \semifilbreak <>= % % \chapcenter macro to produce nice centered chapter titles % \def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in \rightskip=\leftskip \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em \pretolerance=9999 \tolerance=9999 \hyphenpenalty=9999 \exhyphenpenalty=9999} @ %def \chapcenter <>= % \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING} % #1 #2 #3 #4 #5 #6 % % LEVEL: depth; e.g. part=0 chapter=1 sectino=2... % INDENT: indentation of heading from left margin % BEFORESKIP: skip before header % AFTERSKIP: skip after header % STYLE: style of heading; e.g.\bf % HEADING: heading of the sectino % \def\startsection#1#2#3#4#5#6{\par\vskip#3 plus 2in \penalty-200\vskip 0pt plus -2in \noindent{\leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in \hyphenpenalty=9999 \exhyphenpenalty=9999 #5#6\par}\vskip#4% {\def\code##1{[[}\def\edoc##1{]]}\message{[#6]}} \settocparms{#1} \def\themodtitle{#6} %%%% {\def\code{\string\code}\def\edoc{\string\edoc}% \edef\next{\noexpand\write\cont{\tocskip \tocline{\hskip\tocindent\tocstyle\relax\themodtitle} {\noexpand\the\pageno}}}\next % write to toc }% } @ %def \startsection <>= \def\settocparms#1{ \count@=#1 \ifnum\count@<1 \def\tocskip{\vskip3ptplus1in\penalty-100 \vskip0ptplus-1in}% \def\tocstyle{\bf} \def\tocindent{0pt} \else \def\tocskip{} \def\tocstyle{\rm} \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@ \edef\tocindent{\the\dimen@} \fi } @ %def \settocparms <>= \def\tocline#1#2{\line{{\ignorespaces#1}\leaders\hbox to .5em{.\hfil}\hfil \hbox to1.5em{\hss#2}}} @ %def \tocline <>= \def\section#1{\par \vskip3ex\noindent {\bf #1}\par\nobreak\vskip1ex\nobreak} \def\chapter#1{\vfil\eject\startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}} \def\section#1{\startsection{1}{0pt}{4ex}{2ex}{\twlbf}{#1}} \def\subsection#1{\startsection{2}{0pt}{2ex}{1ex}{\bf}{#1}} \def\subsubsection#1{\startsection{3}{0pt}{1ex}{0.5ex}{\it}{#1}} \def\paragraph#1{\startsection{4}{0pt}{1.5ex}{0ex}{\it}{#1}} <> \def\nwfilename#1{\vfil\eject\mark{#1}} \def\nwbegindocs#1{\filbreak} \def\nwenddocs{\par} \def\nwbegincode#1{\par\nobreak \begingroup\setupcode\newlines\parindent=0pt\parskip=0pt \let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef \def\endmoddef{\oendmoddef\par}\def\plusendmoddef{\oplusendmoddef\par}% \hsize=\codehsize\noindent\bchack} \def\nwendcode{\endgroup} {\catcode`\^^M=\active % make CR an active character \gdef\bchack#1^^M{\relax#1}% } @ %def \section \chapter \section \subsection \subsubsection \paragraph @ %def \nwbegindocs \nwenddocs \nwbegincode \nwendcode \nwfilename <>= \edef\contentsfile{\jobname.toc } % file that gets table of contents info \def\readcontents{\expandafter\input \contentsfile} \newwrite\cont \openout\cont=\contentsfile \write\cont{\string\catcode`\string\@=11}% a hack to make contents @ %def \readcontents \cont <>= % take stuff in plain.tex \def\bye{% \write\cont{}% ensure that the contents file isn't empty \closeout\cont \vfil\eject\pageno=-1 % new page causes contents to be really closed \topofcontents\readcontents\botofcontents \vfil\eject\end} \def\topofcontents{\vfil\mark{{\bf Contents}}} \def\botofcontents{} @ %def \bye \topofcontents \botofcontents <>= \let\em=\it % used to produce an itemized (bulleted) list in plain {\TeX} % such lists can be nested % mostly useful with WEB % Usage: % \itemize % \item First thing % \item second thing % \enditemize \newcount\listlevel \listlevel=0 \newdimen\itemwidth \itemwidth=3em \def\itemize{\begingroup\advance\listlevel by1 \def\item{\par\noindent \raise2pt\llap{$\scriptstyle\bullet$\ }\ignorespaces}% \def\nameditem##1{\par\noindent \llap{\rlap{##1}\hskip\itemwidth}\ignorespaces}% \par\advance\leftskip by\itemwidth\advance\rightskip by0.5\itemwidth} \def\enditemize{\par\endgroup\noindent\ignorespaces} \let\begindocument=\relax @ %def \listlevel \itemwidth \itemize \enditemize Finally we make [[@]] `other' again. <>= \catcode`\@=12 @ \section{Chunks} \nowebchunks \twocolumn[\section{Index}] \nowebindex* @ \end{document} pretzel-2.0n-2/contrib/leew/totex0000755000000000000000000005660106250521230015543 0ustar rootroot#!/bin/sh case $# in 0) exec "${ICONX-/a/spelunke/export/vol1/gaertner/icon.9.1/bin/iconx}" "$0";; *) exec "${ICONX-/a/spelunke/export/vol1/gaertner/icon.9.1/bin/iconx}" "$0" "$@";; esac [executable Icon binary follows] \%C CCCCðDÐTXDøEI9.0.00/32p wp@+ £$ £ ³è /÷ãøÐ &œ ,ø yÐh(쌾ÃÉÎ Óßå í÷ü   !-6? G U c my‚ˆŠbC ES<bNC,EST b=bNC8EST Mb=bNC ET3ÿÿý¸bNCDESEEQbMb bNCDESEEQbM¤b bNC+¸UEST b=bNCÿÿÿÈSb,C4EM­b(NC\ES4EEST <b=bb%bNT C<ESbNTSb=:TCDES bNTS3ÿÿûàb=:Sb=:*CˆEM¸b(FT <b=NCŒUES bNCHUES<bNT M ¼b=NES<bNC@UESbNT M Çb=NCLUC ES b8:<C ES b8:ES bNC$T MÒb=NCHUES bNTS Mèb=NCèUC ES b8:ES bNT MøC ES b8: M MC ES b8: M Mb=NC$T Mb=NES ES ES bEbbbNTb=:&ŒCEM )b(NC ES <bNCLT M 6T <b=Mb=NCPUECS8:S EbAbF5NESbEb:%pCðEM Db(NC,TSM Ob=NC,TS M]b=NCDT M dESbMb=NCPUECS8:S EbAbF5NC ESbEbNC ES bEbNC$T M pb=NESES ES bEbbb:#xCðEM}b(NCDT M „ESbMb=NCXT M TESbb=Mb=NCüT MTEST <b=bb=CLEM¦TESbb=b8: MM¨ESSb&M «b=NC@ES EESSb&bbNC ES <bNC ESSbNCHUECS8:SbEbF5NEESSb&Mµb: €CäEM ºb(NCHESbFT<b=NbE:pC ES<bNT M ÇT <b=Mb=:”CèEM Õb(NCœESbFT<b=NC8T M àSMb=NESbEb: T M íb=:¤CDEMúb(NCÔT MTEST <b=bb=CLEM¦TESbb=b8: MMb=NUECS8:SbEbF5:XCÀEM b(NCTEMb(NEST <b=b:@CTEMb(NEST <b=b:äCHEM b(FT <b=NE:”C\EM)b(NTST <b=b=:0CHEM2b(FT <b=NE:àChEM :b(FT <b=NES EbAb:pC\EMDb(NTS T <b=b=: CtEMMb(FT <b=NEESSb&S b:CTEMUb(NEST <b=b:4CTEM^b(NES T <b=b:ØCTEMgb(NES T <b=b:|CHEM pb(FT <b=NE:,CEM |b(NCHEST T3ÿÿê0b=b=bNCEMˆb(NT MŠTT <b=b=MSMb=:ClEM žb(NT M¨T <b=Mb=:¨ClEM °b(NT M»T <b=Mb=:4CdEMÃb(FT <b=NTMÌb=:ÈCHEM Ðb(FT <b=NE:xTEMÚT C(T3ÿÿç¼b=8:<b=bb=:C$EMãb(NC˜EMëb(FT <b=NTC,ES bNMî: M÷b=:`C°ECMù8: M ÿb(NESbFCDT M  ESbMb=NC¼T MTEST <b=bb=M0TSb=MESbMb=NUECS8:SbEbF5: ¨C¬EM4b(NESbFC$UES bNCDT M9ESbMb=NT MNTEST <b=bb=M0TSb=MESbMb=NUECS8:SbEbF5: ôC°EM b(FT <b=NESbFC,TSM Ob=NC,TS M]b=NCDT M dESbMb=NCPUECS8:S EbAbF5NC ESbEbNT M nb=: <CHEM|b(NESbFM„: ìCèEM)b(NESbFC4EST <b=bNT M•TSb=M0TSb=M¥b=:üC|EM2b(FT <b=NESbFT Mb=:xCàEM :b(FT <b=NESbFC,TSM Ob=NC,TS M]b=NCDT M dESbMb=NCPUECS8:S EbAbF5NC ESbEbNC$T M ¨b=NESEbAb:CHEM ¶b(NESbFMÁ:@C(EMDb(NESbFC4EST <b=bNCtT M•TSb=M0TSb=M¥b=NC(TSSb=NE:CTEMMb(FT <b=NESbFC$T Mb=NUESESbbFUT MÝTSb=M0TSb=MESbMb=N5:´C`EM õb(FT <b=NESbFE:LC\EM b(NESbFCHEST T3ÿÿÚ b=b=bNCEMˆb(NC4EST <b=bNTM TSb=M0TSb=MÌb=:èCHEM +b(NESbFM„:˜CHEM 5b(NESbFM„:HC`EM@b(FT <b=NESbFE:àC`EMIb(FT <b=NESbFE:xTEMRT C(T3ÿÿ×b=8:<b=bb=:dCŒEMYb(FT <b=NC ES<bNT M`b=:ÐCŒEM gb(FT <b=NC ESbEbNT Mb=:<C EMqb(NC4EST <b=bNCHUECS8:SbEbF5NC ESb8:4T M àSMb=:(CTEM xb(NT T <b=b=:ÌClEM‚b(NT M=‘T <b=MÏb=:XCDEM áb(NT M îb=: CdEMüb(FT <b=NTM b=: CdEM b(FT <b=NTM'b=:4CäEM,b(NT<T C(T3ÿÿÒœb=8:<b=C(T <b=8:T<b=b=b=:HTb>M .T <b=b=b7N:ÿÿÔLNCTb=NEbD,/ ‚bCPC@EEMYQbM¥bbGDNEbD4/  tzbC0CEEEQbb%<bNC8T M}QMb=NCPUT MEQbMb=F5NC$T Mb=NC EbGD:bDNEbDD1,÷…‹’bC0EEQbM}bNCLQb,C$ESMbNC¸UES4T TQb=b=bNCÿÿÿ¤ES4EQT<b=bbN:ÿÿÿLNC8EST <b=bbGDb7NEbD\3$ ,” ¦¨’˜b;ìCäCESEM}M ªMM¶MM¿MÈMÈMÊMÊMÌMÌMÎMÐM×M×M÷M÷M¦MÙbAbNC,ERT b=bNCÔUJESTSb=bESTSb=bb=NCÿÿÿ€EERSb&TSb=bN:ÿÿÿ0NUESETbbFESMˆbFC,TRSb=N5ENTM6áb=NC$ESMbNCìQb,C„UES4T TTb=b=bNCÿÿÿ¤C4EST<b=bNC˜TRSb=NES4EEMERSb&bMbb:<ES4EM}SbbN:ÿÿþ€NC8EST <b=bbGDb7NEbD 48¤ 7’bC$ESMbNC¤Qb,C<UES4T TMb=b=bNCÿÿÿ CPC$EMb(8: TM b=NC€ES4EM6TT TM>b=b=b=bbNCdES4T ET3ÿÿýàb=<bb=bNCPC$EM>b(8: TMCb=NES4MYbN:ÿÿýÈNC8EST <b=bbGDb7NEbD4;À Baeb;4C,ERTb=bNCÄUC,TRQb=N5ENCTTb>MlQT <b=b=NTRQb=NCC EbGDNEbDD=h O‹’‘˜b; CC,ERT b=bNC<EERMˆb&MžbNC<EERMÌb&M¡bNC<EERMÈb&M¥bNC<EERM÷b&M¨bNC<EERMÊb&M«bNC<EERM®b&M°bNC<EERM´b&M¶bNC<EERM}b&MºbNC<EERMÎb&M½bNC<EERM×b&MÁbNC<EERMb&MÄbNC<EERMb&MÇbNC<EERM¦b&MÊbNC ER3ÿÿû¼bNUER4TRb=b*F5NCdQb,C$ESMbNCÐUES4T TRb=b=bNCÿÿÿ¤ES4EM´ERT<b=b&bbN:ÿÿÿ4NC8EST <b=bbGDb7NEbD° °.ذ/l°0è °2Ȱ8p°;Œ°=$°ÿÿÿ½°ÿÿÿΰÿÿÿ¾°ÿÿÿ¶°ÿÿÿÓ°ÿÿÿ·°ÿÿÿÛ°ÿÿÿϰÿÿÿº°ÿÿÿÙ°ÿÿÿê°ÿÿÿ¿°ÿÿÿÚ°ÿÿÿÀ°ÿÿÿí°ÿÿÿݰÿÿÿðÿÿÿå°ÿÿÿà   , 7 B OZ`eiptz€„‰Ž’™ ¥ª¯³º     ŒO °Øä$ L|  ˜ È Ü ä   8* X œ5 ¨/ °( ¸$ ä) A (.L?h% ”°Ø2$AH/lŒ2¼ä-<,#T |(¬ Ì/;@;l%˜#ÌJÔGÜ8ä)ø $ L „G œ1 ä8!ð5! &" #" @# p$# ¤$$ Ü2% ð!% 8& D& l ' t ' ”#( œ ( Ä1( øJ) G) 8) )) 8* l1* €!* À>+ È=+ à!+ 0J, <D, D9, |4- „3- '- Ð.. ä!, 3/ ('/ 0$/ X'0 €)1 À@2 È=2 ô 3,304P4l,4|54¨&5ØG5ð256<6X,6˜=6´h6¼e6à&7 8XB8d<8l68¤49¬39¸'9ä!8 @;(=;X<|&<¤Y<°S<Ø&=Y= S=4&>P:>„&?°V?¼H?è&@:@8&AT:AtQA€NA¨&BÔVBàHB &C(:CPPC`\Cˆ&D°SD¼MDä&E WEQE@&FhWFtQFœ&G¸:Gì&H$VH0QH<KH`^H˜rI¤nIÐKIü&K,[KDKKp&L [L¸KLä&M:M$JMP&Nl:NÀœNà—Nì‘NôˆN OD'O`2OŒVO¸RO'PDPPiPdWP´ˆQÀ‚QÈ|QðŸQUR(SQd&Sl#Sœ'T´DTØTT pU UUh’VtŒV|†V¤gWÈuWÜUV&Y #YP'Zl9ZˆBZ¸XZìT[$b\8Q\€]Œ]´ ^¼ ^ÜQ_'` B`X'apBa Wa¬Qa܃a ™a ba H'b d9b €Bb  Ub Ì'c è9c!Bc!4Xc!hTd! be!´Qe!üf"f"0 g"8 g"`Qh"€nh"Œkh"´'i"ÌBi#'j#Bj#LWj#XQj#ƒj#¸™j#Ðbj$Ok$4'l$P9l$lBl$”Ul$Àgl$Èdl$üˆm%$žm%H©m%\`m%'n%¬;n%ÈDn%ø'o&Do&Hbo&T]o&`Wo&„jo&´{o&Àuo&ð©p'†q'0zp'\'r'tDr'¬'s'ÄDs'ü't(;t(4Dt(d'u(€;u(œDu(ì¢u) u)—u) u)Lv)hv)”.v)´?v)àw)üw* 1w*(.w*H?w*tx*¤5x*°/x*ð_x*ø\x+ &y+\5y+ˆ{+¬0{+¸,{+ä|,t|,,,|,X~,x,~,¤,À,ä+-€-,€-P+€-|-¸‚-Ø‚-ü+‚.$5‚.0‚.<‚.X „.€=„.Œ „.˜* .À†.Ô‡/ ˆ/8)‰/L2‰/T‰/hŠ/¤ ‹/ÌŒ/ÔŒ/äŒ0 0\Ž0pŽ0¤ 0À0Ô’0ä“10 ”1L•1` •1|–1¤—1ä˜1ð˜1ü ˜2@;˜2L4˜2T(˜2”™2 ™2¨™2´–2Ä›3( 4DŸ4PŸ4x©4„©4¼ª4Ȫ4ì-ª4ø'ª5ª50=ª5HJª5TAª5ˆ«5«5´&«5à:«6¬6@®6\¯6˜°6¤°6° °6ì±6ø ±7$²7l³7t³7ˆ!³7 ³7̵7Ô µ8·8 ·8(·84¯8D¹8¨ º8Ì»8è¼9(½94½9@ ½9x¾9 ¾9ü/¿:*¿:&¿: ¿:( ¿:lÀ:€À:ˆÀ:” À:ÄÁ:ìÁ; Â;XÄ;dÄ;lÄ;x¼;ˆÆ;Ä Ç;ìÉ;øÉ<0Ê<\ Ë<Œ>Ë<˜ Ë<À Ì<äÎ<øÏ=l Ð=œÓ=¨ Ó=Ø Ô=ìÔ> Õ>0Õ>` Ö>tÖ>¤ ×>¸×>è Ø>üØ?, Ù?@Ù?p Ú?„Ú?´ Û?ÈÛ?ø Ü@ Ü@< Ý@PÝ@€ Þ@”Þ@Ä ß@ØßA àAàAD áAtâA€âA¨ äAÐåBæBæB( æB|?æBˆ:æB2æB˜)æBØçBäçBìçBø äCémainlabel2tagdumpitemsescapeTeXspecialsTeXliteralconvquoteswarn_unknownindexlabeltablereadtabwritesposwritematchputuptomovegetstringmemberstopfindmanysetinsertkeyargsdelaynametextuseitemstabdefnsnoindexinputlinelinequotingcodependingusespendingprevpendingnextuseitemsdefitemsnotusedlastdefnlabellastxreflabelthischunklastxrefreffilenamelabeliulist\{}$&#^_ ~%-delay-noindex@text {}\@nl\nwdocspar\nwnewline\nwstartdeflinemarkupnwusesondefline\nwprevnextdefs{\relax}{}\nwenddeflinemarkup@begin code \nwbegincode{@end code nwalsodefinednwused\nwnotused{\nwendcode{}@defn \sublabel{\nwmargintag{\moddef{~}\endmoddefplus@begin docs \nwbegindocs{@end docs \nwfilename{\nwenddocs{}@use \LA{}\RA{}@xref label ref begindefsdefitem enddefsbeginusesuseitem endusesnotused nextdef prevdef beginchunkschunkbegin \nwixlogsorted{c}{{chunkuse \nwixu{chunkdefn \nwixd{chunkend}}%endchunksxref @index nl\eatline%defn localdefn \nosublabel{\nwindexdefn{\nwixident{}}{use \protect\nosublabel{\protect\nwindexuse{\nwixident{\nwidentdefs{isused handled by latex\\{{\nwixident{}}\nwidentuses{isdefined latex finds the definitions\nwindexuse{\nwixident{beginindexentrybegin \nwixlogsorted{i}{{\nwixident{entryuse entrydefn entryendendindexindex @quote{\Tt{}@endquote@file @literal @header latex \documentstyle[noweb]{article}\pagestyle{noweb}\noweboptions{}\begin{document}@header tex \input nwmac @trailer latex\end{document}@trailer tex\bye@Botched line in noweb pipeline: totex.icn{\nwtagstyle{}\subpageref{itemscs\{\\{charsprefixsargnospacecodescnnwbackslashnwlbracenwrbrace$&#^char94_char126internal error, character-code mismatch, report a bug!{\r[[impossible missing [[\code{}]]]impossible missing ]]\edoc{}tagwarnedWarning: unrecognized escape @identbadsettranssphasdopeam,com:colbshatunlbrbtipretzel-2.0n-2/contrib/leew/jtest.nw0000644000000000000000000001352606240700324016152 0ustar rootroot% to weave: % noweave -delay -filter prettyjava -index -backend ./totex jtest.nw > jtest.tex % (-index must be *after* prettyjava) % \documentclass{article} \usepackage{noweb,pp-java,amssymb,multicol} % pp-java package must come *after* noweb \javaclass{aaa} \javaclass{a_long_class_name} \javaclass{another$long$class$name} \javaclass{AbstractClass} \javaclass{FinalClass} \javaclass{PublicClass} \javaclass{AbstractFinal} \javaclass{AbstractPublic} \javaclass{FinalAbstract} \javaclass{FinalPublic} \javaclass{PublicFinal} \javaclass{PublicAbstract} \javaclass{_Forget_It} \javaclass{$forget$this$too$} \javaclass{SomeClass} \javaclass{AnotherClass} \javaclass{Object} \javaclass{OtherClass} \javaclass{Another} \javaclass{Other} \javaclass{String} \begin{document} @ This is a class definition <>= class aaa { <>; } @ %def aaa <>= class a {} class a_long_class_name {} class another$long$class$name {} @ %def a_long_class_name another$long$class$name @ Some extra chunks for sticking places: <>= // empty chunk---Pretzel can't deal with truly empty chunks <>= // empty chunk with math $y = \frac{1}{\sqrt{z}}$ @ Now for some class modifiers: <>= abstract class AbstractClass {} final class FinalClass{} public class PublicClass{} abstract final class AbstractFinal{} abstract public class AbstractPublic{} final abstract class FinalAbstract{} final public class FinalPublic{} public final class PublicFinal{} public abstract class PublicAbstract{} public final abstract class _Forget_It{<>;<>;} public final abstract class $forget$this$too${<>;<>;} @ %def AbstractClass FinalClass AbstractFinal AbstractPublic FinalAbstract PublicFinal PublicAbstract FinalPublic _Forget_It PublicClass $forget$this$too$ @ Now lets try some inheritance: <>= class a extends b {} class x implements y {} class x implements y,z {} class c extends a, b implements y, z {} @ Now for some standard declarations: <>= int x; int y; boolean p = true; float f; boolean p,q = true ,r; float these, are = n+y, non_trivial, names = a+b; SomeClass something; AnotherClass more, than, one; SomeClass less$, $than, ma$ny; @ %def these are non_trivial names something more than one less$ $than ma$ny @ Now the same stuff with modifiers: <>= public int x; private static boolean p,q,r; final private protected float these, are, non_trivial, names, and, the, line, overflows; static SomeClass something; private static AnotherClass more, than, one; @ %def these are non_trivial names something more than one and the line overflows @ Some array declarations: <>= int[] ai; short[][] as; Object[] ao, otherAo; short s, as[], aas[][]; @ %def ai as ao anotherAo as aas @ Importing packages: <>= import java; <>= import java.util.Vector; import java.io.*; <>= import x.y.z.*.*; import a.*.b; class x {} @ Method declarations: <>= void aMethod() { } @ %def aMethod <>= void aMethod(int x) { } @ %def aMethod <>= void aMethod(Otherclass y) { } @ %def aMethod <>= void aMethod(float f, double d) { } @ %def aMethod <>= void aMethod(Other a, Another b) { } @ %def aMethod <>= void aMethod(int a, other b) { } @ %def aMethod <>= void aMethod(other a, int b) { } @ %def aMethod <>= <>; private static SomeClass Method() { <>; <>; <>; int i; } SomeClass Method(int a[], x[] y[]) { } <>; static public private transient boolean Fancy_Method(int a[], boolean[] b, char c[][], double[][][] d)[] throws x,y,z { } @ %def Method Fancy_Method <>= public Constructor(){} AnotherConstructor(a b, c d) throws nothing {} @ %def Constructor AnotherConstructor @ <>= ;; { int i; <>; <>; } label: {super;this;null;} default: null; case xxx: case yyy: case zzz: case hello: this; @ %def label @ <>= "Hello, world\n"; "This \"string\" has quotes (\") in it"; 'Hello, world\n'; 'This \'string\' has quotes in it'; @ <>= +x;-x;~x;!x;new x; <>= x++;++x;x--;--x; <>= (x++);(x--); <>= (++x);(--x); <>= x ? y : z; <>= x>y; x=y; x!=y; x&&y; x||y; x+y; x-y; x*y; x/y; x&y; x|y; x^y; x%y; x<>y; x>>>y; <>= x=y; x+=y; x-=y; x*=y; x/=y; x&=y; x|=y; x^=y; x%=y; x<<=y; x>>=y; x>>>=y; <>= Long_variable = x.a + y * sqrt(george_jr); new double[a][a][]; float[][] matrix= new float[a][]; String[][][][][] fivedims = new String[n][m][o][p][]; (int) x + (float) y * (double[])z / (SomeClass) a; x instanceof String[]; a *= (y+z.a.m.n/x_y_z)^(f(y,z,sqrt(nnn),b+c) == null); x = y[n]; @ %def matrix fivedims @ <>= break; continue; return; break some_label; continue some_label; return x+y*z- -a; throw a/b/c/+z; <>= x = (y[n]+z[m]); synchronized (x) x = y; synchronized (xyz[n]+abc[m]) { <>; } @ Let's look at some numbers: <>= x=y+1; <>= x*=2; x+=0+2+ 0777 +0xDadaCafe +0777777777777777777777L +0x7fffffffffffffffL +0x8000000000000000L +01777777777777777777777L; <>= x-=0+2+0666+0XdADAcAFE +0777777777777777777777l +0X7FFFFFFFFFFFFFFFl +0X8000000000000000l +01777777777777777777777l; <>= 1e1f+2.f+.3f+3.14f+6.02e+23f+1e1+2+.3+3.14+1e-9d <>= 1E1F+2.F+.3F+3.14F+6.02E+23F+1E1+2+.3+3.14+1E-9D <>= class <> extends <> { AbstractPublic ap; <>; aMethod(false, '\u0000', -128, -32768, -3.40292347e+38); aMethod(true, '\uFFFF', +127, +32767, +3.40292347e+38); <> <>; } @ \section*{Identifier Index} \begin{multicols}{2} \nowebindex \end{multicols} \end{document} pretzel-2.0n-2/contrib/leew/index.list0000644000000000000000000000056106360665422016466 0ustar rootrootthis directory & Lee Wittenberg's noweb prettyprinter for Java Makefile & the Makefile (by Felix Gaertner) README & more Information (by Felix Gaertner) java.fg & Pretzel input for Java java.ft & jtest.nw & test file for the prettyprinter pp-java.sty & special LaTeX style needed (see jtest.nw) support.nw & enhanced noweb.sty totex.nw & enhanced Icon version of totex pretzel-2.0n-2/contrib/leew/README0000644000000000000000000000124306255317675015347 0ustar rootrootREADME for Lee Wittenberg's noweb prettyprinter for Java (this file was written by Felix Gaertner) You'll need Icon to run the totex version here. Lee has also updated the noweb.sty (see support.nw) to work nicely with the files prepared here. Note that these versions of support.nw and totex.nw are non-official versions of noweb components. Files: ------ Makefile README this file java.fg Pretzel input for Java java.ft jtest.nw test file for the prettyprinter pp-java.sty special LaTeX style needed (see jtest.nw) support.nw enhanced noweb.sty totex.nw enhanced Icon version of totex Work: ===== Try to `make test' and then latex the jtest.tex file. pretzel-2.0n-2/contrib/leew/java.fg0000644000000000000000000001615106240700323015706 0ustar rootroot/* * java.fg -- experimental Pretzel grammar for Java */ %token BINOP %token BREAK_LIKE %token CASE_LIKE %token CATCH_LIKE %token CHUNK %token COLON %token COMMA %token COMMENT %token DEFAULT_LIKE %token DOT %token DOT_STAR %token DO_LIKE %token ELSE_LIKE %token EXTENDS_LIKE %token FINALLY_LIKE %token FOR_LIKE %token ID_LIKE %token IF_LIKE %token IGNORE %token IMPORT_LIKE %token INCROP %token LBRACE %token LBRACK %token LPAR %token NUM %token QUESTION %token RBRACE %token RBRACK %token RPAR %token SEMI %token STRING %token SYNC_LIKE %token TRY_LIKE %token UNOP %token UNORBINOP %% final : exp { "\\mathin" $1 "\\mathout" } | decl_list | IGNORE | COMMENT | IGNORE final | COMMENT final { $1 force $2 } ; decl_list : decl | decl_list decl { $1 force $2 } ; decl : exp block { "\\mathin" $1 "\\mathout\\ " $2 } ; block : lbrace rbrace { $1 force $2 } | lbrace decl_list rbrace { $1 indent force $2 outdent force $3 } ; exp : expr | exp dot expr | exp comma expr { $1 $2 opt3 "\\mathin" $3 } | exp expr { $1 $2 } ; expr : term | expr binop term { $1 opt9 $2 $3 } | expr unorbinop term { $1 opt9 $2 $3 } | expr extends_like idlist { $1 force "\\ldots" $2 "\\ " $3 } | expr brack_exp ; binop : question exp colon { "\\mathbin{" $1 $2 $3 "}" } ; idlist : ident | idlist comma ident { $1 $2 opt9 $3 } ; ident : id_like | sync_like id_like { $1 "\\ " $2 } | ident id_like { $1 "\\ " $2 } ; brack_exp : lbrack rbrack { $1 "\\thinspace" $2 } | lbrack exp rbrack | brack_exp ident { $1 "\\ " $2 } ; term : factor | unop term { "\\mathin{" $1 $2 "}" } | unorbinop term { "\\mathin{" $1 $2 "}" } | incrop term { "\\mathin{" $1 $2 "}" } | term incrop { "\\mathin{" $1 $2 "}" } ; factor : ident | num | string | lpar rpar { $1 "\\thinspace" $2 } | lpar exp rpar ; decl : block | non_block_stmt ; non_block_stmt : semi { cancel $1 } | exp semi { "\\mathin" $1 "\\mathout" $2 } | break_like semi | break_like exp semi { $1 "\\ \\mathin" $2 "\\mathout" $3 } | sync_like lpar exp rpar decl { $1 "\\ \\mathin" $2 $3 $4 "\\mathout\\ " $5 } | import_head semi | label colon decl { force backup $1 $2 force $3 } | try_stmt | if_block | if_simple | else_head block { $1 "\\ " $2 } | else_head non_block_stmt { $1 indent force $2 outdent } | for_stmt | do_stmt ; import_head : import_like id_like { $1 "\\ " $2 } | import_head dot id_like | import_head dot_star ; if_head : if_like lpar exp rpar { $1 "\\ \\mathin" $2 $3 $4 "\\mathout" } ; if_block : if_head block { $1 "\\ " $2 } ; if_simple : if_head non_block_stmt { $1 indent force $2 outdent } ; else_head : else_like | if_block else_like { $1 "\\ " $2 } | if_simple else_like { $1 force $2 } ; try_stmt : try_like block { $1 "\\ " $2 } | try_stmt finally_like block { $1 "\\ " $2 "\\ " $3 } | try_stmt catch_like lpar exp rpar block { $1 "\\ \\mathin" $2 $3 $4 $5 "\\mathout\\ " $6 } ; label : default_like | case_like exp { $1 "\\ \\mathin" $2 "\\mathout"} | id_like ; do_stmt : do_like block if_head semi { $1 "\\ " $2 "\\ " $3 $4 } | do_like non_block_stmt if_head semi { $1 indent force $2 outdent $3 $4 } ; for_head : for_like lpar for_control rpar { $1 "\\ " $2 $3 $4 } ; for_control : opt_exp semi opt_exp semi opt_exp ; opt_exp : // empty | exp { "\\mathin" $1 "\\mathout" } ; for_stmt : for_head block { $1 "\\ " $2 } | for_head non_block_stmt { $1 indent force $2 outdent } ; // rules to pass comments and ignores through unnoticed binop : BINOP | binop IGNORE | binop COMMENT { $1 "\\qquad" break_space $2 force } ; break_like : BREAK_LIKE | break_like IGNORE | break_like COMMENT { $1 "\\qquad" break_space $2 force } ; case_like : CASE_LIKE | case_like IGNORE | case_like COMMENT { $1 "\\qquad" break_space $2 force } ; catch_like : CATCH_LIKE | catch_like IGNORE | catch_like COMMENT { $1 "\\qquad" break_space $2 force } ; colon : COLON | colon IGNORE | colon COMMENT { $1 "\\qquad" break_space $2 force } ; comma : COMMA | comma IGNORE | comma COMMENT { $1 "\\qquad" break_space $2 force } ; default_like : DEFAULT_LIKE | default_like IGNORE | default_like COMMENT { $1 "\\qquad" break_space $2 force } ; dot : DOT | dot IGNORE | dot COMMENT { $1 "\\qquad" break_space $2 force } ; dot_star : DOT_STAR | dot_star IGNORE | dot_star COMMENT { $1 "\\qquad" break_space $2 force } ; do_like : DO_LIKE | do_like IGNORE | do_like COMMENT { $1 "\\qquad" break_space $2 force } ; else_like : ELSE_LIKE | else_like IGNORE | else_like COMMENT { $1 "\\qquad" break_space $2 force } ; extends_like : EXTENDS_LIKE | extends_like IGNORE | extends_like COMMENT { $1 "\\qquad" break_space $2 force } ; finally_like : FINALLY_LIKE | finally_like IGNORE | finally_like COMMENT { $1 "\\qquad" break_space $2 force } ; for_like : FOR_LIKE | for_like IGNORE | for_like COMMENT { $1 "\\qquad" break_space $2 force } ; id_like : ID_LIKE | CHUNK | id_like IGNORE | id_like COMMENT { $1 "\\qquad" break_space $2 force } ; if_like : IF_LIKE | if_like IGNORE | if_like COMMENT { $1 "\\qquad" break_space $2 force } ; import_like : IMPORT_LIKE | import_like IGNORE | import_like COMMENT { $1 "\\qquad" break_space $2 force } ; incrop : INCROP | incrop IGNORE | incrop COMMENT { $1 "\\qquad" break_space $2 force } ; lbrace : LBRACE | lbrace IGNORE | lbrace COMMENT { $1 "\\qquad" break_space $2 force cancel } ; lbrack : LBRACK | lbrack IGNORE | lbrack COMMENT { $1 "\\qquad" break_space $2 force } ; lpar : LPAR | lpar IGNORE | lpar COMMENT { $1 "\\qquad" break_space $2 force } ; num : NUM | num IGNORE | num COMMENT { $1 "\\qquad" break_space $2 force } ; question : QUESTION | question IGNORE | question COMMENT { $1 "\\qquad" break_space $2 force } ; rbrace : RBRACE | rbrace IGNORE | rbrace COMMENT { $1 "\\qquad" break_space $2 force } ; rbrack : RBRACK | rbrack IGNORE | rbrack COMMENT { $1 "\\qquad" break_space $2 force } ; rpar : RPAR | rpar IGNORE | rpar COMMENT { $1 "\\qquad" break_space $2 force } ; semi : SEMI | semi IGNORE | semi COMMENT { $1 "\\qquad" break_space $2 force cancel } ; string : STRING | string IGNORE | string COMMENT { $1 "\\qquad" break_space $2 force } ; sync_like : SYNC_LIKE | sync_like IGNORE | sync_like COMMENT { $1 "\\qquad" break_space $2 force } ; try_like : TRY_LIKE | try_like IGNORE | try_like COMMENT { $1 "\\qquad" break_space $2 force } ; unop : UNOP | unop IGNORE | unop COMMENT { $1 "\\qquad" break_space $2 force } ; unorbinop : UNORBINOP | unorbinop IGNORE | unorbinop COMMENT { $1 "\\qquad" break_space $2 force } ; %% pretzel-2.0n-2/contrib/leew/index.html0000644000000000000000000000237006360665431016457 0ustar rootroot Index file for directory "pretzel/contrib/leew" of Pretzel distribution

Index file for directory "pretzel/contrib/leew" of Pretzel distribution

Files and directories are:

this directory

    Lee Wittenberg's noweb prettyprinter for Java
Makefile
    the Makefile (by Felix Gaertner)
README
    more Information (by Felix Gaertner)
java.fg
    Pretzel input for Java
java.ft
jtest.nw
    test file for the prettyprinter
pp-java.sty
    special LaTeX style needed (see jtest.nw)
support.nw
    enhanced noweb.sty
totex.nw
    enhanced Icon version of totex

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 12:42:34 MESZ 1997 pretzel-2.0n-2/contrib/leew/Makefile0000644000000000000000000000103206255320176016111 0ustar rootroot# $Id: Makefile,v 1.2 1996/12/16 19:18:22 gaertner Exp $ #---------------------------------------------------------------------- # # Makefile for Lee Wittenberg's Java prettyprinting filter for noweb # test: prettyjava noweave -delay -filter prettyjava -index -backend ./totex jtest.nw > jtest.tex prettyjava: java.ft java.fg pretzel-it -n java prettyjava totex: totex.nw notangle < totex.nw > totex.icn icont totex.icn noweb.sty: support.nw notangle -Rnoweb.sty > noweb.sty clean: rm -f *.tex *.log *.dvi *.o *.toc *.aux pretzel-2.0n-2/contrib/leew/totex.diff0000644000000000000000000000776106250521503016455 0ustar rootroot67c67 < if ="@begin docs " then { if \delay & match(0) then <> --- > if ="@begin docs " then { if \delay & match(0) then <> 69c69 < if ="@end docs " then { if \delay & match(0) then <> --- > if ="@end docs " then { if \delay & match(0) then <> 102c102 < writes("\\moddef{", convquotes(thischunk := tab(0)), --- > writes("\\moddef{", convquotes(thischunk := tab(0)), 115c115 < if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)), --- > if ="@use " then { writes("\\LA{}", convquotes(name := tab(0)), 124c124 < [[defns]] serves only to give the proper distinction between --- > [[defns]] serves only to give the proper distinction between 131c131 < if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\Tt{}") } else --- > if ="@quote" & pos(0) then { quoting := 1 ; writes("{\\tt{}") } else 189c189 < writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{", --- > writes("\\nwprevnextdefs{", \pendingprev | "\\relax", "}{", 214c214 < Unless it's OK to show the index (by \LA{}SI\RA), we handle nothing but --- > Unless it's OK to show the index (by \LA{}SI\RA), we handle nothing but 231c231 < writes("\\nwindexdefn{\\nwixident{", TeXliteral(name := tab(0)), "}}{", indexlabel(name), "}{", --- > writes("\\nwindexdefn{", TeXliteral(name := tab(0)), "}{", indexlabel(name), "}{", 240c240 < writes("\\protect\\nwindexuse{\\nwixident{", TeXliteral(name := tab(0)), "}}{", --- > writes("\\protect\\nwindexuse{", TeXliteral(name := tab(0)), "}{", 256c256 < if ="useitem " then <> { i := tab(0); <> --- > if ="useitem " then <> { i := tab(0); <> 260c260 < writes("\\\\{{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}}") --- > writes("\\\\{{", TeXliteral(i), "}{", indexlabel(i), "}}") 262,264c262,264 < every i := !ulist do < writes("\\nwindexuse{\\nwixident{", TeXliteral(i), "}}{", indexlabel(i), "}{", \lastdefnlabel, "}") < @ --- > every i := !ulist do > writes("\\nwindexuse{", TeXliteral(i), "}{", indexlabel(i), "}{", \lastdefnlabel, "}") > @ 281,282c281,282 < write("\\nwixlogsorted{i}{{\\nwixident{", TeXliteral(name), < "}}{", indexlabel(name), "}}%") } else --- > write("\\nwixlogsorted{i}{{", TeXliteral(name), > "}{", indexlabel(name), "}}%") } else 307,320d306 < < Unfortunately, the character codes for these characters are not the < same across fonts. While this is not a problem when everything is in < a typewriter font, it can cause major strangenesses when another font < is used (Icon, for example, is often typeset in a sans-serif font). < Codes for `[[$]]', `[[&]]', `[[#]]', `[[^]]', `[[_]]', `[[~]]' and < `[[%]]' use < font-independent macros. Since there is no font-independent way to < typeset `[[\]]', `[[{]]' and `[[}]]',\footnote{Although both plain < \TeX\ and \LaTeX\ provide `[[\{]]' and `[[\}]], plain \TeX\ only < allows their use in math mode.} < we generate special macros defined in \verb"noweb.sty" and < \verb"nwmac.tex". The default definitions are geared to typewriter < fonts, but they can be redefined as necessary. 324,333c310,311 < initial { codes := ["\\", "nwbackslash", < "{", "nwlbrace", < "}", "nwrbrace", < "$", "$", < "&", "&", < "#", "#", < "^", "char94", < "_", "_", < "%", "%", < "~", "char126"] --- > initial { codes := ["\\", 92, "{", 123, "}", 125, "$", 36, "&", 38, "#", 35, "^", 94, > "_", 95, "%", 37, "~", 126] 344c322 < s ||:= "{\\" || code[c] || "}" --- > s ||:= "{\\char" || code[c] || "}" 352c330 < A special function is used to implement {\tt noweb}'s quoting --- > A special function is used to implement {\tt noweb}'s quoting pretzel-2.0n-2/contrib/leew/pp-java.sty0000644000000000000000000001112106240700324016537 0ustar rootroot\codehsize=\textwidth \nwdefspace=0pt % to put xrefs at right margin (where they belong) \def\@begincode{% \trivlist \item[]% \leftskip\@totalleftmargin \advance\leftskip\codemargin \rightskip\hsize \advance\rightskip -\codehsize \parskip\z@ \parindent\z@ \parfillskip\@flushglue \linewidth\codehsize \nowebsize \let\maybehbox\mbox \let\eatline=\relax } \newcount\ind \newenvironment{ppcode}{% \sfcode`;=3000 % a `;' acts like a period \pretolerance=10000 % \hyphenpenalty=10000 % \exhyphenpenalty=10000 % \global\ind=2 % This fakeout is important for opt to work correctly \par \global\hangindent\ind em }{% \mathout } \newbox\bak\setbox\bak=\hbox to -1em{} % backspace 1 em \newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace 2 ems \def\pretzelindent{\global\advance\ind by1\hangindent\ind em}% \def\pretzeloutdent{\global\advance\ind by-1}% \def\pretzelopt#1{\hfil\penalty#10\hfilneg}% \def\pretzelbackup{\copy\bak}% \def\pretzelbreakspace{\hfil\penalty-1\hfilneg \kern2.5em\copy\bakk\ignorespaces}% % parm below is to eat {} generated by Pretzel \def\pretzelforce#1{\mathout\par\hangindent\ind em\noindent \kern\ind em\copy\bakk#1\ignorespaces}% \def\pretzelbigforce{\mathout\par\smallskip\pretzelforce}% \def\pretzelnoindent{\hskip-\ind em\hskip 2em}% \def\mathin{\ifmmode\else\begin{math}\fi{}} \def\mathout{\ifmmode\end{math}\fi{}} \def\javakey#1{\mbox{\bf#1}} {\catcode`\_=\active\catcode`\$=\active % Note: The double braces when defining _ and $ in \javaclass % and \java@id are necessary to deal correctly with \csname \gdef\javaclass{\bgroup\catcode`\_=\active\catcode`\$=\active \def_{{!}}\def${{?}}\java@class}% \gdef\javaid{\bgroup\catcode`\_=\active\catcode`\$=\active \let_=\_\let$=\$\java@id}% \gdef\java@id#1{{\def_{{!}}\def\_{!}\def${{?}}\def\${?}% \@ifundefined{java@id@#1}% {\global\let\java@idfont@local=\it}% {\global\let\java@idfont@local=\bf}% }\mbox{\java@idfont@local#1}\egroup}% \gdef\Tt{\catcode`\_=\active\let_=\_\It}% } \def\java@class#1{\expandafter\gdef\csname java@id@#1\endcsname{x}\egroup} \def\javacomment//#1\javacomment{\mbox{$/\!/${}#1}} \def\pretzelbreakspace{\hfil\penalty-1\hfilneg \kern2.5em\copy\bakk\ignorespaces}% \def\java@resumemath{\\mathin{}} \def\javaassign#1{\buildrel\;#1\over{\gets}} \catcode`\^^K=\other % for \verb* with strings \def\javaint#1{\java@num{int}{#1}} \def\javaoct#1{\java@num{oct}{#1}} \def\javahex#1{\java@num{hex}{#1}} \def\javadec#1{\java@num{dec}{#1}} \let\java@intfont=\rm \let\java@octfont=\it \let\java@hexfont=\tt \let\java@decfont=\rm \let\java@intprefix=\null \def\java@octprefix{{$^\circ$}\kern-.2em} \def\java@hexprefix{{$^{\scriptscriptstyle\#}$}} \let\java@decprefix=\null \let\java@intsuffix=\null \let\java@octsuffix=\null \let\java@hexsuffix=\null \let\java@decsuffix=\null \def\java@num#1#2{\mbox{% \csname java@#1prefix\endcsname \csname java@#1font\endcsname \csname java@#1\endcsname #2\end \csname java@#1suffix\endcsname }} \def\java@int#1{\let\java@next=\java@int \ifx#1\end\let\java@next=\relax\else \ifx#1l\java@suffix{long}\else \ifx#1L\java@suffix{long}\else #1% \fi\fi\fi\java@next } \def\java@suffix#1{\kern.1em{$_{\mathbf{#1}}$}} \def\java@oct0{\java@int} \def\java@hex0#1{\java@int} % #1 is to ignore initial X or x \def\java@dec#1{\let\java@next=\java@dec \ifx#1\end\let\java@next=\relax\else \ifx#1D\java@suffix{double}\else \ifx#1d\java@suffix{double}\else \ifx#1F\java@suffix{float}\else \ifx#1f\java@suffix{float}\else \ifx#1E\let\java@next=\java@edec$\cdot10^\bgroup\else \ifx#1e\let\java@next=\java@edec$\cdot10^\bgroup\else #1% \fi\fi\fi\fi\fi\fi\fi\java@next } \def\java@edec#1{\let\java@next=\java@edec \ifx#1\end\egroup$\let\java@next=\relax\else \ifx#1D\egroup_{\mathbf{double}}$\let\java@next=\java@dec\else \ifx#1d\egroup_{\mathbf{double}}$\let\java@next=\java@dec\else \ifx#1F\egroup_{\mathbf{float}}$\let\java@next=\java@dec\else \ifx#1f\egroup_{\mathbf{float}}$\let\java@next=\java@dec\else #1% \fi\fi\fi\fi\fi\java@next } % hacks so that the index and mini-indexes will work with our % jury-rigged back end \let\java@iddefs=\nwidentdefs \let\java@iduses=\nwidentuses {\catcode`\_=\active \gdef\nwidentdefs{\bgroup\catcode`\_=\active\def_{!}\java@helpdefs}% \gdef\nwidentuses{\bgroup\catcode`\_=\active\def_{!}\java@helpuses}% } \def\java@helpdefs#1{\java@iddefs{#1}\egroup} \def\java@helpuses#1{\java@iduses{#1}\egroup} \let\java@ixlog=\nwixlogsorted \def\nwixlogsorted#1#2{% \ifx#1i\immediate\write\@auxout{\string\bgroup \string\catcode`\string\_=\string\active}\fi \java@ixlog{#1}{#2}% \ifx#1i\immediate\write\@auxout{\string\egroup}\fi } \let\nwixident=\javaid pretzel-2.0n-2/contrib/leew/java.ft0000644000000000000000000000650606240700323015726 0ustar rootroot/* * java.ft -- experimental Pretzel token file for Java */ ALPH [a-zA-Z_$] ALPHNUM [a-zA-Z0-9_$] DIGIT [0-9] DECDIGIT [0-9] OCTDIGIT [0-7] HEXDIGIT [0-9A-Fa-f] EXP ([eE][+-]?[0-9]+) %% // // symbols "{" LBRACE {"\\{"} "}" RBRACE {"\\}"} "(" LPAR ")" RPAR "[" LBRACK "]" RBRACK ";" SEMI {"\\mathout; "} ":" COLON {":"} "," COMMA {"\\mathout, "} "." DOT {"{.}"} "+" | "-" UNORBINOP "=" BINOP {"\\gets"} "<" | ">" BINOP "!" UNOP {"\\lnot"} "~" UNOP {"\\mathord{\\sim}"} "?" QUESTION {"\\mathrel?"} "==" BINOP {"\\equiv"} "<=" BINOP {"\\leq"} ">=" BINOP {"\\geq"} "!=" BINOP {"\\neq"} "||" BINOP {"\\lor"} "&&" BINOP {"\\land"} "++" | "--" INCROP {"\\mbox{\\tt" + ** + "}"} "*" BINOP {"\\times"} "/" BINOP {"\\div"} "&" BINOP {"\\mathrel{\\&}"} "|" BINOP {"\\mid"} "^" BINOP {"\\oplus"} "%" BINOP {"\\mathbin{\\%}"} "<<" BINOP {"\\ll"} ">>" BINOP {"\\gg"} ">>>" BINOP {"\\ggg"} // needs amssymb package "+=" BINOP {"\\javaassign{+}"} "-=" BINOP {"\\javaassign{-}"} "*=" BINOP {"\\javaassign{\\times}"} "/=" BINOP {"\\javaassign{\\div}"} "&=" BINOP {"\\javaassign{\\&}"} "|=" BINOP {"\\javaassign{\\mid}"} "^=" BINOP {"\\javaassign{\\oplus}"} "%=" BINOP {"\\javaassign{\\%}"} "<<=" BINOP {"\\javaassign{\\ll}"} ">>=" BINOP {"\\javaassign{\\gg}"} ">>>=" BINOP {"\\javaassign{\\ggg}"} // needs amssymb package "//".* COMMENT {"\\javacomment" + ** + "\\javacomment"} // // keywords "new" UNOP {"\\javakey{" + ** + "}\\ "} "instanceof" BINOP {"\\in"} // alternate: {"\\mathrel{\\javakey{" + ** + "}}"} "null" ID_LIKE {"\\mathin\\Lambda"} "class" | "interface" | "void" | "boolean" | "byte" | "char" | "double" | "float" | "int" | "long" | "short" | "abstract" | "final" | "native" | "protected" | "private" | "public" | "static" | "transient" | "volatile" | "true" | "false" | "super" | "this" ID_LIKE {"\\javakey{" + ** + "}"} "case" CASE_LIKE {"\\javakey{" + ** + "}"} "default" DEFAULT_LIKE {"\\javakey{" + ** + "}"} "synchronized" SYNC_LIKE {"\\javakey{" + ** + "}"} "try" TRY_LIKE {"\\javakey{" + ** + "}"} "catch" CATCH_LIKE {"\\javakey{" + ** + "}"} "finally" FINALLY_LIKE {"\\javakey{" + ** + "}"} "if" | "switch" | "while" IF_LIKE {"\\javakey{" + ** + "}"} "else" ELSE_LIKE {"\\javakey{" + ** + "}"} "for" FOR_LIKE {"\\javakey{" + ** + "}"} "do" DO_LIKE {"\\javakey{" + ** + "}"} "break" | "continue" | "return" | "throw" BREAK_LIKE {"\\javakey{" + ** + "}"} "throws" | "extends" | "implements" EXTENDS_LIKE {"\\javakey{" + ** + "}"} "package" | "import" IMPORT_LIKE {"\\javakey{" + ** + "}"} ".*" DOT_STAR {"\\mathin.\\mathord{\\ast}"} // // misc ^"@use\ ".* CHUNK { "\n" + ** + "\n" } ^"@".* IGNORE { "\n" + ** + "\n" } 0[lL]? | [1-9]{DECDIGIT}*[lL]? NUM {"\\javaint{" + ** + "}"} 0{OCTDIGIT}+[lL]? NUM {"\\javaoct{" + ** + "}"} 0[xX]{HEXDIGIT}{HEXDIGIT}*[lL]? NUM {"\\javahex{" + ** + "}"} {DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]? | "."{DECDIGIT}+{EXP}?[fdFD]? | {DECDIGIT}+{EXP}[fdFD]? NUM {"\\javadec{" + ** + "}"} [a-zA-Z] ID_LIKE {"\\mathin{" + ** + "}"} // math italic for one-char ids {ALPH}{ALPHNUM}* ID_LIKE {"%\n@index use " + ** + "\n\\javaid{" + ** + "}"} '([^']|\\')*' | \"([^\"]|\\\")*\" STRING {"\\verb*\013" + ** + "\013"} [\ \t\n] // gobble up whitespace . // ignore all non-standard chars // (bug in Pretzel?) %% pretzel-2.0n-2/contrib/index.html0000644000000000000000000000171206360666271015525 0ustar rootroot Index file for directory "pretzel/contrib" of Pretzel distribution

Index file for directory "pretzel/contrib" of Pretzel distribution

Files and directories are:

this directory

    contributed software for Pretzel
huhr
    Holger Uhr's enhanced Java Prettyprinter for noweb
leew
    Lee Wittenbergs first Java Prettyprinter for noweb
noweb
    more stuff on noweb contributed by Felix Gaertner :-)

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 12:49:30 MESZ 1997 pretzel-2.0n-2/contrib/huhr/0000755000000000000000000000000006367034376014477 5ustar rootrootpretzel-2.0n-2/contrib/huhr/index.list0000644000000000000000000000022006360666130016465 0ustar rootrootthis directory & Enhancements to Lee Wittenberg's Java Prettyprinter by Holger Uhr README & More Information javahu.fg & The formatted grammar pretzel-2.0n-2/contrib/huhr/README0000644000000000000000000000037306360663736015363 0ustar rootrootThis is the Java prettyprinter by Lee Wittenberg with slight modifications sent to me by Holger Uhr It basicly replaces the file java.fg in the directory contrib/leew of the Pretzel distribution, but I haven't tried it. FG pretzel-2.0n-2/contrib/huhr/javahu.fg0000644000000000000000000001646106360663427016301 0ustar rootroot/* * javahu.fg -- experimental Pretzel grammar for Java */ /* original filename java.fg * (slight changes to java.fg by Lee Wittenberg) * by Holger Uhr */ %token BINOP %token BREAK_LIKE %token CASE_LIKE %token CATCH_LIKE %token CHUNK %token COLON %token COMMA %token COMMENT %token DEFAULT_LIKE %token DOT %token DOT_STAR %token DO_LIKE %token ELSE_LIKE %token EXTENDS_LIKE %token FINALLY_LIKE %token FOR_LIKE %token ID_LIKE %token IF_LIKE %token IGNORE %token IMPORT_LIKE %token INCROP %token LBRACE %token LBRACK %token LPAR %token NUM %token QUESTION %token RBRACE %token RBRACK %token RPAR %token SEMI %token STRING %token SYNC_LIKE %token TRY_LIKE %token UNOP %token UNORBINOP %% final : exp { "\\mathin" $1 "\\mathout" } | decl_list { cancel $1 cancel } | IGNORE | COMMENT { $1 force } | IGNORE final | COMMENT final { $1 force $2 } ; decl_list : decl | decl_list decl { $1 force $2 } ; decl : exp block { big_force "\\mathin" $1 "\\mathout\\ " $2 big_force } ; block : lbrace rbrace { $1 force $2 } | lbrace decl_list rbrace { $1 indent force $2 cancel outdent force $3 } ; exp : expr | exp dot expr | exp comma expr { $1 $2 opt3 "\\mathin" $3 } | exp expr { $1 $2 } ; expr : term | expr binop term { $1 opt9 $2 $3 } | expr unorbinop term { $1 opt9 $2 $3 } | expr extends_like idlist { $1 force "\\ldots" $2 "\\ " $3 } | expr brack_exp ; binop : question exp colon { "\\mathbin{" $1 $2 $3 "}" } ; idlist : ident | idlist comma ident { $1 $2 opt9 $3 } ; ident : id_like | sync_like id_like { $1 "\\ " $2 } | ident id_like { $1 "\\ " $2 } ; brack_exp : lbrack rbrack { $1 "\\thinspace" $2 } | lbrack exp rbrack | brack_exp ident { $1 "\\ " $2 } ; term : factor | unop term { "\\mathin{" $1 $2 "}" } | unorbinop term { "\\mathin{" $1 $2 "}" } | incrop term { "\\mathin{" $1 $2 "}" } | term incrop { "\\mathin{" $1 $2 "}" } ; factor : ident | num | string | lpar rpar { $1 "\\thinspace" $2 } | lpar exp rpar ; decl : block | non_block_stmt ; non_block_stmt : semi { cancel $1 } | exp semi { "\\mathin" $1 "\\mathout" $2 } | break_like semi | break_like exp semi { $1 "\\ \\mathin" $2 "\\mathout" $3 } | sync_like lpar exp rpar decl { $1 "\\ \\mathin" $2 $3 $4 "\\mathout\\ " $5 } | import_head semi | label colon decl { force backup $1 $2 force $3 } | try_stmt | if_block | if_simple | else_head block { $1 "\\ " $2 } | else_head non_block_stmt { $1 indent force $2 outdent } | for_stmt | do_stmt | CHUNK { $1 force } // Holger Uhr ; import_head : import_like id_like { $1 "\\ " $2 } | import_head dot id_like | import_head dot_star ; if_head : if_like lpar exp rpar { $1 "\\ \\mathin" $2 $3 $4 "\\mathout" } ; if_block : if_head block { $1 "\\ " $2 } ; if_simple : if_head non_block_stmt { $1 indent force $2 outdent } ; else_head : else_like | if_block else_like { $1 "\\ " $2 } | if_simple else_like { $1 force $2 } ; try_stmt : try_like block { $1 "\\ " $2 } | try_stmt finally_like block { $1 "\\ " $2 "\\ " $3 } | try_stmt catch_like lpar exp rpar block { $1 "\\ \\mathin" $2 $3 $4 $5 "\\mathout\\ " $6 } ; label : default_like | case_like exp { $1 "\\ \\mathin" $2 "\\mathout"} | id_like ; do_stmt : do_like block if_head semi { $1 "\\ " $2 "\\ " $3 $4 } | do_like non_block_stmt if_head semi { $1 indent force $2 outdent $3 $4 } ; for_head : for_like lpar for_control rpar { $1 "\\ " $2 $3 $4 } ; for_control : opt_exp semi opt_exp semi opt_exp ; opt_exp : // empty | exp { "\\mathin" $1 "\\mathout" } ; for_stmt : for_head block { $1 "\\ " $2 } | for_head non_block_stmt { $1 indent force $2 outdent } ; // rules to pass comments and ignores through unnoticed binop : BINOP | binop IGNORE | binop COMMENT { $1 "\\qquad" break_space $2 force } ; break_like : BREAK_LIKE | break_like IGNORE | break_like COMMENT { $1 "\\qquad" break_space $2 force } ; case_like : CASE_LIKE | case_like IGNORE | case_like COMMENT { $1 "\\qquad" break_space $2 force } ; catch_like : CATCH_LIKE | catch_like IGNORE | catch_like COMMENT { $1 "\\qquad" break_space $2 force } ; colon : COLON | colon IGNORE | colon COMMENT { $1 "\\qquad" break_space $2 force } ; comma : COMMA | comma IGNORE | comma COMMENT { $1 "\\qquad" break_space $2 force } ; default_like : DEFAULT_LIKE | default_like IGNORE | default_like COMMENT { $1 "\\qquad" break_space $2 force } ; dot : DOT | dot IGNORE | dot COMMENT { $1 "\\qquad" break_space $2 force } ; dot_star : DOT_STAR | dot_star IGNORE | dot_star COMMENT { $1 "\\qquad" break_space $2 force } ; do_like : DO_LIKE | do_like IGNORE | do_like COMMENT { $1 "\\qquad" break_space $2 force } ; else_like : ELSE_LIKE | else_like IGNORE | else_like COMMENT { $1 "\\qquad" break_space $2 force } ; extends_like : EXTENDS_LIKE | extends_like IGNORE | extends_like COMMENT { $1 "\\qquad" break_space $2 force } ; finally_like : FINALLY_LIKE | finally_like IGNORE | finally_like COMMENT { $1 "\\qquad" break_space $2 force } ; for_like : FOR_LIKE | for_like IGNORE | for_like COMMENT { $1 "\\qquad" break_space $2 force } ; id_like : ID_LIKE | id_like IGNORE | id_like COMMENT { $1 "\\qquad" break_space $2 force } ; if_like : IF_LIKE | if_like IGNORE | if_like COMMENT { $1 "\\qquad" break_space $2 force } ; import_like : IMPORT_LIKE | import_like IGNORE | import_like COMMENT { $1 "\\qquad" break_space $2 force } ; incrop : INCROP | incrop IGNORE | incrop COMMENT { $1 "\\qquad" break_space $2 force } ; lbrace : LBRACE | lbrace IGNORE | lbrace COMMENT { $1 "\\qquad" break_space $2 force } ; lbrack : LBRACK | lbrack IGNORE | lbrack COMMENT { $1 "\\qquad" break_space $2 force } ; lpar : LPAR | lpar IGNORE | lpar COMMENT { $1 "\\qquad" break_space $2 force } ; num : NUM | num IGNORE | num COMMENT { $1 "\\qquad" break_space $2 force } ; question : QUESTION | question IGNORE | question COMMENT { $1 "\\qquad" break_space $2 force } ; rbrace : RBRACE | rbrace IGNORE | rbrace COMMENT { $1 "\\qquad" break_space $2 force } ; rbrack : RBRACK | rbrack IGNORE | rbrack COMMENT { $1 "\\qquad" break_space $2 force } ; rpar : RPAR | rpar IGNORE | rpar COMMENT { $1 "\\qquad" break_space $2 force } ; semi : SEMI | semi IGNORE | semi COMMENT { $1 "\\qquad" break_space $2 force } ; string : STRING | string IGNORE | string COMMENT { $1 "\\qquad" break_space $2 force } ; sync_like : SYNC_LIKE | sync_like IGNORE | sync_like COMMENT { $1 "\\qquad" break_space $2 force } ; try_like : TRY_LIKE | try_like IGNORE | try_like COMMENT { $1 "\\qquad" break_space $2 force } ; unop : UNOP | unop IGNORE | unop COMMENT { $1 "\\qquad" break_space $2 force } ; unorbinop : UNORBINOP | unorbinop IGNORE | unorbinop COMMENT { $1 "\\qquad" break_space $2 force } ; %% pretzel-2.0n-2/contrib/aj/0000755000000000000000000000000010765024520014106 5ustar rootrootpretzel-2.0n-2/contrib/aj/gcl.lex.c0000644000000000000000000014212010765024517015614 0ustar rootroot/* A lexical scanner generated by flex */ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include #include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 54 #define YY_END_OF_BUFFER 55 static yyconst short int yy_accept[107] = { 0, 0, 0, 55, 54, 53, 23, 54, 34, 1, 3, 31, 30, 8, 25, 7, 32, 50, 11, 5, 26, 36, 27, 49, 2, 4, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 54, 54, 24, 54, 38, 9, 0, 6, 39, 50, 12, 28, 37, 29, 49, 22, 49, 49, 49, 49, 49, 17, 20, 19, 49, 49, 49, 49, 18, 16, 49, 49, 49, 0, 21, 0, 10, 49, 49, 49, 43, 33, 45, 40, 41, 35, 49, 49, 42, 0, 0, 0, 49, 49, 47, 49, 13, 44, 51, 0, 14, 15, 49, 49, 52, 49, 49, 52, 48, 46, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 1, 6, 1, 7, 1, 1, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 20, 21, 1, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 1, 25, 1, 1, 1, 26, 27, 28, 29, 30, 31, 32, 23, 33, 23, 34, 35, 36, 37, 38, 39, 23, 40, 41, 42, 43, 44, 45, 46, 47, 23, 48, 49, 50, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[52] = { 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1 } ; static yyconst short int yy_base[110] = { 0, 0, 103, 124, 126, 126, 103, 116, 126, 126, 126, 126, 126, 126, 108, 106, 99, 102, 97, 126, 96, 95, 94, 0, 126, 64, 25, 74, 73, 20, 77, 23, 29, 28, 27, 83, 87, 83, 126, 63, 126, 126, 84, 126, 126, 88, 126, 126, 126, 126, 0, 126, 65, 62, 63, 63, 55, 0, 0, 0, 56, 51, 59, 66, 0, 0, 61, 66, 49, 67, 126, 44, 126, 44, 57, 47, 0, 0, 51, 0, 0, 0, 41, 40, 0, 59, 37, 47, 34, 28, 44, 41, 0, 0, 52, 66, 0, 0, 43, 38, 0, 29, 24, 0, 0, 0, 126, 60, 87, 90 } ; static yyconst short int yy_def[110] = { 0, 106, 1, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 107, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 106, 106, 106, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 106, 107, 107, 107, 107, 107, 107, 108, 106, 107, 107, 107, 107, 109, 107, 107, 109, 107, 107, 0, 106, 106, 106 } ; static yyconst short int yy_nxt[178] = { 0, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 4, 23, 24, 25, 26, 27, 28, 29, 23, 30, 23, 31, 23, 23, 32, 23, 33, 23, 23, 34, 23, 23, 35, 23, 23, 23, 36, 37, 4, 38, 52, 56, 59, 61, 86, 64, 57, 65, 60, 66, 62, 50, 105, 53, 104, 63, 102, 101, 100, 86, 67, 99, 98, 97, 96, 95, 86, 93, 92, 91, 90, 89, 88, 87, 86, 94, 85, 84, 85, 103, 83, 103, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 45, 72, 71, 70, 69, 68, 58, 55, 54, 51, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 106, 39, 3, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106 } ; static yyconst short int yy_chk[178] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 29, 31, 32, 86, 33, 29, 33, 31, 34, 32, 107, 102, 26, 101, 32, 99, 98, 95, 94, 34, 91, 90, 89, 88, 87, 85, 83, 82, 78, 75, 74, 73, 71, 69, 86, 108, 68, 108, 109, 67, 109, 66, 63, 62, 61, 60, 56, 55, 54, 53, 52, 45, 42, 39, 37, 36, 35, 30, 28, 27, 25, 22, 21, 20, 18, 17, 16, 15, 14, 7, 6, 3, 2, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "gcl.l" #define INITIAL 0 /************************************************ * This is a flex file generated by pretzel * * * ************************************************/ #line 7 "gcl.l" /* some needed headers: */ #include #include"attr.h" /* we'll define yywrap() which is needed for the scanner * here, so we won't have to bother about it if we're * doing the standard case. You can define your own version * by #undef'ing PSCAN_YYWRAP and supplying your own definition * in the definitions section. */ #define PSCAN_YYWRAP /* input will come from this istream */ static istream * yyin_stream; /* redefine YYINPUT to read from input streams */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } #line 38 "gcl.l" char *typeset_pred(char *pred); /************************************************ * some pretzel definitions start here: * ***********************************************/ #line 48 "gcl.l" /* the default name of the include file with the token * code definitions is stored in PTOKDEFS_NAME and * defaults to `ptokdefs'. */ #ifndef PTOKDEFS_NAME #define PTOKDEFS_NAME "ptokdefs.h" #endif /* now we have to include the token definitions */ #include PTOKDEFS_NAME /* allow user to choose generated scanner class name*/ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* redefine the interface of the scanner */ #undef YY_DECL #define YY_DECL int yylex (Attribute**rvalue) /* here's the standard version of yywrap() */ #ifdef PSCAN_YYWRAP extern "C" int yywrap() { return(1); } #endif /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ if ( yyleng > 0 ) \ yy_current_buffer->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 80 "gcl.l" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_current_state += YY_AT_BOL(); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 126 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 83 "gcl.l" {*rvalue=create(yytext);return (OPEN);} YY_BREAK case 2: YY_RULE_SETUP #line 86 "gcl.l" {*rvalue=create(yytext);return (OPEN);} YY_BREAK case 3: YY_RULE_SETUP #line 89 "gcl.l" {*rvalue=create(yytext);return (CLOSE);} YY_BREAK case 4: YY_RULE_SETUP #line 92 "gcl.l" {*rvalue=create(yytext);return (CLOSE);} YY_BREAK case 5: YY_RULE_SETUP #line 95 "gcl.l" { *rvalue=join( create(";")); return(SEMI);} YY_BREAK case 6: YY_RULE_SETUP #line 101 "gcl.l" {*rvalue=create(yytext);return (DOTDOT);} YY_BREAK case 7: YY_RULE_SETUP #line 104 "gcl.l" {*rvalue=create(yytext);return (DOT);} YY_BREAK case 8: YY_RULE_SETUP #line 107 "gcl.l" { *rvalue=join( create(", ")); return(COMMA);} YY_BREAK case 9: YY_RULE_SETUP #line 113 "gcl.l" { *rvalue=join( create("$[]$")); return(BLOCK);} YY_BREAK case 10: YY_RULE_SETUP #line 119 "gcl.l" { *rvalue=join( create("$\\longrightarrow$")); return(ARROW);} YY_BREAK case 11: YY_RULE_SETUP #line 125 "gcl.l" { *rvalue=join( create(" : ")); return(COLON);} YY_BREAK case 12: YY_RULE_SETUP #line 131 "gcl.l" { *rvalue=join( create("$\\leftarrow$")); return(BECOMES);} YY_BREAK case 13: YY_RULE_SETUP #line 137 "gcl.l" { *rvalue=join( create("\\underline{\\bf skip}")); return(SKIP);} YY_BREAK case 14: YY_RULE_SETUP #line 143 "gcl.l" { *rvalue=join( create("\\underline{\\bf abort}")); return(ABORT);} YY_BREAK case 15: YY_RULE_SETUP #line 149 "gcl.l" { *rvalue=join( create("{\\bf array}")); return(ARRAY);} YY_BREAK case 16: YY_RULE_SETUP #line 155 "gcl.l" { *rvalue=join( create("{\\bf of}")); return(OF);} YY_BREAK case 17: YY_RULE_SETUP #line 161 "gcl.l" { *rvalue=join( create("\\underline{\\bf do}")); return(DO);} YY_BREAK case 18: YY_RULE_SETUP #line 167 "gcl.l" { *rvalue=join( create("\\underline{\\bf od}")); return(OD);} YY_BREAK case 19: YY_RULE_SETUP #line 173 "gcl.l" { *rvalue=join( create("\\underline{\\bf if}")); return(IF);} YY_BREAK case 20: YY_RULE_SETUP #line 179 "gcl.l" { *rvalue=join( create("\\underline{\\bf fi}")); return(FI);} YY_BREAK case 21: YY_RULE_SETUP #line 185 "gcl.l" { *rvalue=join( create("$|[$")); return(OPENBLOCK);} YY_BREAK case 22: YY_RULE_SETUP #line 191 "gcl.l" { *rvalue=join( create("$]|$")); return(CLOSEBLOCK);} YY_BREAK case 23: YY_RULE_SETUP #line 197 "gcl.l" { *rvalue=join( create("$\\neg$")); return(UNARY_OP);} YY_BREAK case 24: YY_RULE_SETUP #line 203 "gcl.l" { *rvalue=join( create("$\\neg$")); return(UNARY_OP);} YY_BREAK case 25: YY_RULE_SETUP #line 209 "gcl.l" {*rvalue=create(yytext);return (MINUS);} YY_BREAK case 26: YY_RULE_SETUP #line 212 "gcl.l" { *rvalue=join( create("$<$")); return(BINARY_OP);} YY_BREAK case 27: YY_RULE_SETUP #line 218 "gcl.l" { *rvalue=join( create("$>$")); return(BINARY_OP);} YY_BREAK case 28: YY_RULE_SETUP #line 224 "gcl.l" { *rvalue=join( create("$\\leq$")); return(BINARY_OP);} YY_BREAK case 29: YY_RULE_SETUP #line 230 "gcl.l" { *rvalue=join( create("$\\geq$")); return(BINARY_OP);} YY_BREAK case 30: YY_RULE_SETUP #line 236 "gcl.l" {*rvalue=create(yytext);return (BINARY_OP);} YY_BREAK case 31: YY_RULE_SETUP #line 239 "gcl.l" { *rvalue=join( create("$\\times$")); return(BINARY_OP);} YY_BREAK case 32: YY_RULE_SETUP #line 245 "gcl.l" { *rvalue=join( create("\\underline{\\bf div}")); return(BINARY_OP);} YY_BREAK case 33: YY_RULE_SETUP #line 251 "gcl.l" { *rvalue=join( create("\\underline{\\bf div}")); return(BINARY_OP);} YY_BREAK case 34: YY_RULE_SETUP #line 257 "gcl.l" { *rvalue=join( create("\\underline{\\bf mod}")); return(BINARY_OP);} YY_BREAK case 35: YY_RULE_SETUP #line 263 "gcl.l" { *rvalue=join( create("\\underline{\\bf mod}")); return(BINARY_OP);} YY_BREAK case 36: YY_RULE_SETUP #line 269 "gcl.l" { *rvalue=join( create("$=$")); return(BINARY_OP);} YY_BREAK case 37: YY_RULE_SETUP #line 275 "gcl.l" { *rvalue=join( create("$=$")); return(BINARY_OP);} YY_BREAK case 38: YY_RULE_SETUP #line 281 "gcl.l" { *rvalue=join( create("$\\neq$")); return(BINARY_OP);} YY_BREAK case 39: YY_RULE_SETUP #line 287 "gcl.l" { *rvalue=join( create("$\\neq$")); return(BINARY_OP);} YY_BREAK case 40: YY_RULE_SETUP #line 293 "gcl.l" { *rvalue=join( create("\\underline{\\bf max}")); return(BINARY_OP);} YY_BREAK case 41: YY_RULE_SETUP #line 299 "gcl.l" { *rvalue=join( create("\\underline{\\bf min}")); return(BINARY_OP);} YY_BREAK case 42: YY_RULE_SETUP #line 305 "gcl.l" { *rvalue=join( create("\\underline{\\bf var}")); return(ACCESS);} YY_BREAK case 43: YY_RULE_SETUP #line 311 "gcl.l" { *rvalue=join( create("\\underline{\\bf con}")); return(ACCESS);} YY_BREAK case 44: YY_RULE_SETUP #line 317 "gcl.l" { *rvalue=join( create("\\underline{\\bf swap}")); return(SWAP);} YY_BREAK case 45: YY_RULE_SETUP #line 323 "gcl.l" { *rvalue=join( create("{\\bf integer}")); return(TYPE);} YY_BREAK case 46: YY_RULE_SETUP #line 329 "gcl.l" { *rvalue=join( create("{\\bf integer}")); return(TYPE);} YY_BREAK case 47: YY_RULE_SETUP #line 335 "gcl.l" { *rvalue=join( create("{\\bf boolean}")); return(TYPE);} YY_BREAK case 48: YY_RULE_SETUP #line 341 "gcl.l" { *rvalue=join( create("{\\bf boolean}")); return(TYPE);} YY_BREAK case 49: YY_RULE_SETUP #line 347 "gcl.l" { *rvalue=join( join( join( create("$\\mathit{"), create(yytext) ), create("}$") )); return(ID);} YY_BREAK case 50: YY_RULE_SETUP #line 359 "gcl.l" { *rvalue=join( join( join( create("$"), create(yytext) ), create("$") )); return(NUMBER);} YY_BREAK case 51: YY_RULE_SETUP #line 371 "gcl.l" { *rvalue=join( join( join( create("$\\{"), create(typeset_pred(yytext)) ), create(" \\}$") )); return(PREDICATE);} YY_BREAK case 52: YY_RULE_SETUP #line 383 "gcl.l" { *rvalue=join( join( join( create("\n"), create(yytext) ), create("\n") )); return(CHUNK);} YY_BREAK case 53: YY_RULE_SETUP #line 395 "gcl.l" /* empty */ YY_BREAK case 54: YY_RULE_SETUP #line 398 "gcl.l" ECHO; YY_BREAK case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; yy_current_state += YY_AT_BOL(); for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 107 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 106); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; yy_current_buffer->yy_at_bol = (c == '\n'); return c; } #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifndef YY_ALWAYS_INTERACTIVE #ifndef YY_NEVER_INTERACTIVE extern int isatty YY_PROTO(( int )); #endif #endif #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif #line 398 "gcl.l" /************************************************ * additional pretzel C code follows here: * ***********************************************/ PSCAN_NAME::PSCAN_NAME (istream* is ) : Pscan(is) { yyin_stream = is; } PSCAN_NAME::scan(Attribute* *rvalue) { return(yylex(rvalue)); } PSCAN_NAME::~PSCAN_NAME () { yyrestart(NULL); } /************************************************ * additional user defined C code follows here: * ***********************************************/ pretzel-2.0n-2/contrib/aj/gcl.fg0000644000000000000000000000377306537722705015217 0ustar rootroot %token PREDICATE %token CHUNK %token SEMI %token OPEN %token CLOSE %token DOTDOT %token DOT %token BECOMES %token BLOCK %token COMMA %token ARROW %token COLON %token SKIP %token ABORT %token ARRAY %token OF %token DO %token OD %token IF %token FI %token SWAP %token OPENBLOCK %token CLOSEBLOCK %token UNARY_OP %token MINUS %token BINARY_OP %token ACCESS %token TYPE %token ID %token NUMBER %% stmt_list : stmt | predicate stmt { $1 force $2 } | predicate stmt predicate { $1 force $2 force $3 } | stmt predicate { $1 force $2 } | stmt SEMI stmt_list { $1 $2 force $3 } | predicate stmt SEMI stmt_list { $1 force $2 $3 force $4 } ; predicate : PREDICATE | PREDICATE predicate { $1 force $2 } ; stmt : selection | repetition | block | SWAP simple_expr DOT simple_expr DOT simple_expr { $1 " " $2 $3 $4 $5 $6 } | SKIP | ABORT | CHUNK | assign ; assign : expr_list BECOMES expr_list { $1 " " $2 " " indent opt5 outdent $3 } ; expr_list : expr | expr COMMA expr_list { $1 $2 " " opt9 $3 } ; simple_expr : ID | NUMBER | OPEN expr CLOSE ; expr : simple_expr | ID DOT simple_expr | UNARY_OP simple_expr | expr binary_op expr { $1 " " $2 " " $3 } ; binary_op : BINARY_OP | MINUS ; unary_op : UNARY_OP | MINUS ; repetition : DO guarded_list OD { $1 " " $2 force $3 } ; selection : IF guarded_list FI { $1 " " $2 force $3 } ; guarded_list : guarded_stmt | guarded_stmt BLOCK guarded_list { $1 force $2 " " $3 } ; guarded_stmt : expr ARROW stmt_list { $1 " " $2 indent force $3 outdent } ; block : OPENBLOCK decls stmt_list CLOSEBLOCK { $1 indent force $2 force $3 outdent force $4 } ; decls : decl | decl decls ; decl : ACCESS type_decls SEMI { $1 " " $2 " " $3 force } ; type_decls : type_decl | type_decl COMMA type_decls { $1 $2 " " $3 } ; type_decl : expr_list COLON type { $1 " " $2 " " $3 } ; type : TYPE | ARRAY bounds OF TYPE { $1 " " $2 " " $3 " " $4 } ; bounds : OPEN expr DOTDOT expr CLOSE ; pretzel-2.0n-2/contrib/aj/ptokdefs.h0000644000000000000000000000111006537754156016110 0ustar rootroot#ifndef YYSTYPE #define YYSTYPE int #endif #define PREDICATE 258 #define CHUNK 259 #define SEMI 260 #define OPEN 261 #define CLOSE 262 #define DOTDOT 263 #define DOT 264 #define BECOMES 265 #define BLOCK 266 #define COMMA 267 #define ARROW 268 #define COLON 269 #define SKIP 270 #define ABORT 271 #define ARRAY 272 #define OF 273 #define DO 274 #define OD 275 #define IF 276 #define FI 277 #define SWAP 278 #define OPENBLOCK 279 #define CLOSEBLOCK 280 #define UNARY_OP 281 #define MINUS 282 #define BINARY_OP 283 #define ACCESS 284 #define TYPE 285 #define ID 286 #define NUMBER 287 pretzel-2.0n-2/contrib/aj/gcl.y0000644000000000000000000002501106537754155015064 0ustar rootroot/************************************************** * This is a prettyprinting parser implementation * * file generated by pretzel. (It's Bison code!) * * * *************************************************/ %{ /* this is needed for the yyprint function below */ #include /* include the attribute definitions */ #include"attr.h" /* include the output definitions */ #include"output.h" /* enable parser debugging */ #define YYDEBUG 1 /* redefine the semantic value */ #define YYSTYPE Attribute* /* enable calls of YYPRINT */ #define YYPRINT(file, type, value) yyprint (file, type, value) /* this is the prototype for yyprint */ static void yyprint(FILE *file, int type, YYSTYPE value); /* make sure that our local copy of yylex is * declared with name `yylex' and as a static * function. This should trick the parser into * calling the scanner object stored in * `static_scanner' (see below). */ /* undefine yylex to make sure it isn't renamed * by any command line option (e.g. -P). */ #undef yylex /* declare our local `dummy' yylex */ static int yylex(YYSTYPE *rvalue); /* make sure any newer versions of Bison don't * redeclare it differently */ #define YYLEX_DECL %} /************************************************* * various user definitions start here: * *************************************************/ %token PREDICATE %token CHUNK %token SEMI %token OPEN %token CLOSE %token DOTDOT %token DOT %token BECOMES %token BLOCK %token COMMA %token ARROW %token COLON %token SKIP %token ABORT %token ARRAY %token OF %token DO %token OD %token IF %token FI %token SWAP %token OPENBLOCK %token CLOSEBLOCK %token UNARY_OP %token MINUS %token BINARY_OP %token ACCESS %token TYPE %token ID %token NUMBER /************************************************* * some pretzel definitions start here: * ************************************************/ %{ /* include own header only in default case: */ #ifndef PPARSE_NAME #include "Ppparse.h" #endif /* this is a definition of the yyerror routine */ yyerror (const char *s) { /* ignore error messages by BISON */ /* trick! use s do get around warning `s not used'. */ if (1==0) fprintf(stderr, "%s", s); return 0; } /* enable parser debugging */ #define YYDEBUG 1 /* variable to hold the parsed attribute */ static Attribute *rest=create(null); /* include the scanner only in the default case: */ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* trick the yyparse function to use the scan member * of the scanner class: */ static Pscan* static_scanner = NULL; static int yylex( YYSTYPE *rvalue ) { return(static_scanner->scan(rvalue)); } %} %pure_parser %% stmt_list : stmt {rest=$$=$1;} | predicate stmt { rest=$$= join( join( $1, create(force)), $2); } | predicate stmt predicate { rest=$$= join( join( join( join( $1, create(force)), $2), create(force)), $3); } | stmt predicate { rest=$$= join( join( $1, create(force)), $2); } | stmt SEMI stmt_list { rest=$$= join( join( join( $1, $2), create(force)), $3); } | predicate stmt SEMI stmt_list { rest=$$= join( join( join( join( join( $1, create(force)), $2), $3), create(force)), $4); } ; predicate : PREDICATE {rest=$$=$1;} | PREDICATE predicate { rest=$$= join( join( $1, create(force)), $2); } ; stmt : selection {rest=$$=$1;} | repetition {rest=$$=$1;} | block {rest=$$=$1;} | SWAP simple_expr DOT simple_expr DOT simple_expr { rest=$$= join( join( join( join( join( join( $1, create(" ")), $2), $3), $4), $5), $6); } | SKIP {rest=$$=$1;} | ABORT {rest=$$=$1;} | CHUNK {rest=$$=$1;} | assign {rest=$$=$1;} ; assign : expr_list BECOMES expr_list { rest=$$= join( join( join( join( join( join( join( $1, create(" ")), $2), create(" ")), create(indent)), create(opt5)), create(outdent)), $3); } ; expr_list : expr {rest=$$=$1;} | expr COMMA expr_list { rest=$$= join( join( join( join( $1, $2), create(" ")), create(opt9)), $3); } ; simple_expr : ID {rest=$$=$1;} | NUMBER {rest=$$=$1;} | OPEN expr CLOSE {rest=$$=join($1,join($2,$3));} ; expr : simple_expr {rest=$$=$1;} | ID DOT simple_expr {rest=$$=join($1,join($2,$3));} | UNARY_OP simple_expr {rest=$$=join($1,$2);} | expr binary_op expr { rest=$$= join( join( join( join( $1, create(" ")), $2), create(" ")), $3); } ; binary_op : BINARY_OP {rest=$$=$1;} | MINUS {rest=$$=$1;} ; unary_op : UNARY_OP {rest=$$=$1;} | MINUS {rest=$$=$1;} ; repetition : DO guarded_list OD { rest=$$= join( join( join( join( $1, create(" ")), $2), create(force)), $3); } ; selection : IF guarded_list FI { rest=$$= join( join( join( join( $1, create(" ")), $2), create(force)), $3); } ; guarded_list : guarded_stmt {rest=$$=$1;} | guarded_stmt BLOCK guarded_list { rest=$$= join( join( join( join( $1, create(force)), $2), create(" ")), $3); } ; guarded_stmt : expr ARROW stmt_list { rest=$$= join( join( join( join( join( join( $1, create(" ")), $2), create(indent)), create(force)), $3), create(outdent)); } ; block : OPENBLOCK decls stmt_list CLOSEBLOCK { rest=$$= join( join( join( join( join( join( join( join( $1, create(indent)), create(force)), $2), create(force)), $3), create(outdent)), create(force)), $4); } ; decls : decl {rest=$$=$1;} | decl decls {rest=$$=join($1,$2);} ; decl : ACCESS type_decls SEMI { rest=$$= join( join( join( join( join( $1, create(" ")), $2), create(" ")), $3), create(force)); } ; type_decls : type_decl {rest=$$=$1;} | type_decl COMMA type_decls { rest=$$= join( join( join( $1, $2), create(" ")), $3); } ; type_decl : expr_list COLON type { rest=$$= join( join( join( join( $1, create(" ")), $2), create(" ")), $3); } ; type : TYPE {rest=$$=$1;} | ARRAY bounds OF TYPE { rest=$$= join( join( join( join( join( join( $1, create(" ")), $2), create(" ")), $3), create(" ")), $4); } ; bounds : OPEN expr DOTDOT expr CLOSE {rest=$$=join($1,join($2,join($3,join($4,$5))));} ; %% /************************************************* * additional pretzel code starts here: * *************************************************/ #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif PPARSE_NAME::PPARSE_NAME() { } PPARSE_NAME::~PPARSE_NAME() { static_scanner = NULL; } int PPARSE_NAME::prettyprint(istream* is, ostream* os) { Latex_cweb_output ppoutput(*os); return(prettyprint(is, &ppoutput)); } int PPARSE_NAME::prettyprint(istream* is, Output* outp) { int ret_val = 0; PSCAN_NAME ppscanner(is); static_scanner = &ppscanner; ret_val=yyparse(); while (!(is->eof())) { char c; is->get(c); } rest->print(*outp); return(ret_val); } void PPARSE_NAME::debug_on() { yydebug = 1; } void PPARSE_NAME::debug_off() { yydebug = 0; } /* This is a routine to print the semantic value */ static void yyprint(FILE *file, int type, YYSTYPE value) { Latex_cweb_output os(cerr); value->print(os); } /************************************************* * optional user defined C code follows here: * *************************************************/ pretzel-2.0n-2/contrib/aj/gcl.tab.c0000644000000000000000000011153206537754156015610 0ustar rootroot /* A Bison parser, made from gcl.y by GNU Bison version 1.25 */ #define YYBISON 1 /* Identify Bison output. */ #define PREDICATE 258 #define CHUNK 259 #define SEMI 260 #define OPEN 261 #define CLOSE 262 #define DOTDOT 263 #define DOT 264 #define BECOMES 265 #define BLOCK 266 #define COMMA 267 #define ARROW 268 #define COLON 269 #define SKIP 270 #define ABORT 271 #define ARRAY 272 #define OF 273 #define DO 274 #define OD 275 #define IF 276 #define FI 277 #define SWAP 278 #define OPENBLOCK 279 #define CLOSEBLOCK 280 #define UNARY_OP 281 #define MINUS 282 #define BINARY_OP 283 #define ACCESS 284 #define TYPE 285 #define ID 286 #define NUMBER 287 #line 7 "gcl.y" /* this is needed for the yyprint function below */ #include /* include the attribute definitions */ #include"attr.h" /* include the output definitions */ #include"output.h" /* enable parser debugging */ #define YYDEBUG 1 /* redefine the semantic value */ #define YYSTYPE Attribute* /* enable calls of YYPRINT */ #define YYPRINT(file, type, value) yyprint (file, type, value) /* this is the prototype for yyprint */ static void yyprint(FILE *file, int type, YYSTYPE value); /* make sure that our local copy of yylex is * declared with name `yylex' and as a static * function. This should trick the parser into * calling the scanner object stored in * `static_scanner' (see below). */ /* undefine yylex to make sure it isn't renamed * by any command line option (e.g. -P). */ #undef yylex /* declare our local `dummy' yylex */ static int yylex(YYSTYPE *rvalue); /* make sure any newer versions of Bison don't * redeclare it differently */ #define YYLEX_DECL #line 94 "gcl.y" /* include own header only in default case: */ #ifndef PPARSE_NAME #include "Ppparse.h" #endif /* this is a definition of the yyerror routine */ yyerror (const char *s) { /* ignore error messages by BISON */ /* trick! use s do get around warning `s not used'. */ if (1==0) fprintf(stderr, "%s", s); return 0; } /* enable parser debugging */ #define YYDEBUG 1 /* variable to hold the parsed attribute */ static Attribute *rest=create(null); /* include the scanner only in the default case: */ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* trick the yyparse function to use the scan member * of the scanner class: */ static Pscan* static_scanner = NULL; static int yylex( YYSTYPE *rvalue ) { return(static_scanner->scan(rvalue)); } #ifndef YYSTYPE #define YYSTYPE int #endif #include #ifndef __cplusplus #ifndef __STDC__ #define const #endif #endif #define YYFINAL 85 #define YYFLAG -32768 #define YYNTBASE 33 #define YYTRANSLATE(x) ((unsigned)(x) <= 287 ? yytranslate[x] : 52) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; #if YYDEBUG != 0 static const short yyprhs[] = { 0, 0, 2, 5, 9, 12, 16, 21, 23, 26, 28, 30, 32, 39, 41, 43, 45, 47, 51, 53, 57, 59, 61, 65, 67, 71, 74, 78, 80, 82, 84, 86, 90, 94, 96, 100, 104, 109, 111, 114, 118, 120, 124, 128, 130, 135 }; static const short yyrhs[] = { 35, 0, 34, 35, 0, 34, 35, 34, 0, 35, 34, 0, 35, 5, 33, 0, 34, 35, 5, 33, 0, 3, 0, 3, 34, 0, 42, 0, 41, 0, 45, 0, 23, 38, 9, 38, 9, 38, 0, 15, 0, 16, 0, 4, 0, 36, 0, 37, 10, 37, 0, 39, 0, 39, 12, 37, 0, 31, 0, 32, 0, 6, 39, 7, 0, 38, 0, 31, 9, 38, 0, 26, 38, 0, 39, 40, 39, 0, 28, 0, 27, 0, 26, 0, 27, 0, 19, 43, 20, 0, 21, 43, 22, 0, 44, 0, 44, 11, 43, 0, 39, 13, 33, 0, 24, 46, 33, 25, 0, 47, 0, 47, 46, 0, 29, 48, 5, 0, 49, 0, 49, 12, 48, 0, 37, 14, 50, 0, 30, 0, 17, 51, 18, 30, 0, 6, 39, 8, 39, 7, 0 }; #endif #if YYDEBUG != 0 static const short yyrline[] = { 0, 136, 137, 146, 159, 168, 179, 196, 197, 208, 209, 210, 211, 228, 229, 230, 231, 234, 255, 256, 271, 272, 273, 276, 277, 278, 279, 294, 295, 298, 299, 302, 317, 332, 333, 348, 367, 390, 391, 394, 411, 412, 425, 440, 441, 460 }; #endif #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) static const char * const yytname[] = { "$","error","$undefined.","PREDICATE", "CHUNK","SEMI","OPEN","CLOSE","DOTDOT","DOT","BECOMES","BLOCK","COMMA","ARROW", "COLON","SKIP","ABORT","ARRAY","OF","DO","OD","IF","FI","SWAP","OPENBLOCK","CLOSEBLOCK", "UNARY_OP","MINUS","BINARY_OP","ACCESS","TYPE","ID","NUMBER","stmt_list","predicate", "stmt","assign","expr_list","simple_expr","expr","binary_op","repetition","selection", "guarded_list","guarded_stmt","block","decls","decl","type_decls","type_decl", "type","bounds", NULL }; #endif static const short yyr1[] = { 0, 33, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 36, 37, 37, 38, 38, 38, 39, 39, 39, 39, 40, 40, -1, -1, 41, 42, 43, 43, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51 }; static const short yyr2[] = { 0, 1, 2, 3, 2, 3, 4, 1, 2, 1, 1, 1, 6, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 1, 3, 2, 3, 1, 1, 1, 1, 3, 3, 1, 3, 3, 4, 1, 2, 3, 1, 3, 3, 1, 4, 5 }; static const short yydefact[] = { 0, 7, 15, 0, 13, 14, 0, 0, 0, 0, 0, 20, 21, 0, 1, 16, 0, 23, 18, 10, 9, 11, 8, 0, 0, 0, 33, 0, 20, 0, 0, 0, 37, 25, 0, 2, 0, 4, 0, 0, 28, 27, 0, 22, 0, 31, 0, 32, 0, 0, 0, 40, 0, 38, 24, 0, 3, 5, 17, 19, 26, 35, 34, 0, 0, 39, 0, 36, 6, 0, 0, 43, 42, 41, 12, 0, 0, 0, 0, 0, 44, 0, 45, 0, 0, 0 }; static const short yydefgoto[] = { 52, 13, 14, 15, 16, 17, 18, 42, 19, 20, 25, 26, 21, 31, 32, 50, 51, 72, 76 }; static const short yypact[] = { 47, 15,-32768, -1,-32768,-32768, -1, -1, 3, -17, 3, 24,-32768, 71, 11,-32768, 14,-32768, 53,-32768,-32768, -32768,-32768, 0, 27, 16, 41, 20,-32768, 48, -1, 47, -17,-32768, 3, 12, 47,-32768, -1, -1,-32768, -32768, -1,-32768, 47,-32768, -1,-32768, 3, 46, 56, 52, 44,-32768,-32768, 47,-32768,-32768,-32768,-32768, -6, -32768,-32768, 65, -4,-32768, -1,-32768,-32768, 3, 76, -32768,-32768,-32768,-32768, -1, 66, 21, 55, -1,-32768, 31,-32768, 83, 88,-32768 }; static const short yypgoto[] = { 1, 9, 78,-32768, -19, -2, -3,-32768,-32768,-32768, -5, -32768,-32768, 57,-32768, 30,-32768,-32768,-32768 }; #define YYLAST 103 static const short yytable[] = { 23, 83, 27, 24, 24, 3, 29, 43, 33, 3, 22, 49, 30, 70, 1, 1, 36, 55, 1, 58, 59, 40, 41, 37, 38, 10, 71, 40, 41, 79, 11, 12, 54, 34, 28, 12, 45, 57, 82, 60, 44, 62, 47, 24, 56, 61, 63, 49, 40, 41, 1, 2, 46, 3, 40, 41, 68, 48, 40, 41, 64, 65, 4, 5, 66, 39, 6, 74, 7, 67, 8, 9, 77, 10, 69, 2, 81, 3, 11, 12, 40, 41, 75, 84, 78, 80, 4, 5, 85, 53, 6, 35, 7, 0, 8, 9, 73, 10, 0, 0, 0, 0, 11, 12 }; static const short yycheck[] = { 3, 0, 7, 6, 7, 6, 8, 7, 10, 6, 1, 30, 29, 17, 3, 3, 5, 5, 3, 38, 39, 27, 28, 14, 10, 26, 30, 27, 28, 8, 31, 32, 34, 9, 31, 32, 20, 36, 7, 42, 13, 46, 22, 46, 35, 44, 48, 66, 27, 28, 3, 4, 11, 6, 27, 28, 55, 9, 27, 28, 14, 5, 15, 16, 12, 12, 19, 69, 21, 25, 23, 24, 75, 26, 9, 4, 79, 6, 31, 32, 27, 28, 6, 0, 18, 30, 15, 16, 0, 32, 19, 13, 21, -1, 23, 24, 66, 26, -1, -1, -1, -1, 31, 32 }; #define YYPURE 1 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/local/gnu/lib/bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ #ifndef alloca #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) #include #else /* not sparc */ #if defined (MSDOS) && !defined (__TURBOC__) #include #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) #include #pragma alloca #else /* not MSDOS, __TURBOC__, or _AIX */ #ifdef __hpux #ifdef __cplusplus extern "C" { void *alloca (unsigned int); }; #else /* not __cplusplus */ void *alloca (); #endif /* not __cplusplus */ #endif /* __hpux */ #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ #endif /* not sparc. */ #endif /* not GNU C. */ #endif /* alloca not defined. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT return(0) #define YYABORT return(1) #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYPURE #define YYLEX yylex() #endif #ifdef YYPURE #ifdef YYLSP_NEEDED #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) #else #define YYLEX yylex(&yylval, &yylloc) #endif #else /* not YYLSP_NEEDED */ #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, YYLEX_PARAM) #else #define YYLEX yylex(&yylval) #endif #endif /* not YYLSP_NEEDED */ #endif /* If nonreentrant, generate the variables here */ #ifndef YYPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* not YYPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers from coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ int yyparse (void); #endif #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (to, from, count) char *to; char *from; int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #else /* __cplusplus */ /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (char *to, char *from, int count) { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #endif #endif #line 196 "/usr/local/gnu/lib/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM #ifdef __cplusplus #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM #define YYPARSE_PARAM_DECL #else /* not __cplusplus */ #define YYPARSE_PARAM_ARG YYPARSE_PARAM #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; #endif /* not __cplusplus */ #else /* not YYPARSE_PARAM */ #define YYPARSE_PARAM_ARG #define YYPARSE_PARAM_DECL #endif /* not YYPARSE_PARAM */ int yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { register int yystate; register int yyn; register short *yyssp; register YYSTYPE *yyvsp; int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yychar1 = 0; /* lookahead token as an internal (translated) token number */ short yyssa[YYINITDEPTH]; /* the state stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ short *yyss = yyssa; /* refer to the stacks thru separate pointers */ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ #ifdef YYLSP_NEEDED YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else #define YYPOPSTACK (yyvsp--, yyssp--) #endif int yystacksize = YYINITDEPTH; #ifdef YYPURE int yychar; YYSTYPE yylval; int yynerrs; #ifdef YYLSP_NEEDED YYLTYPE yylloc; #endif #endif YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Starting parse\n"); #endif yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss - 1; yyvsp = yyvs; #ifdef YYLSP_NEEDED yylsp = yyls; #endif /* Push a new state, which is found in yystate . */ /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yynewstate: *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Give user a chance to reallocate the stack */ /* Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; #ifdef YYLSP_NEEDED YYLTYPE *yyls1 = yyls; #endif /* Get the current used size of the three stacks, in elements. */ int size = yyssp - yyss + 1; #ifdef yyoverflow /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ #ifdef YYLSP_NEEDED /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yyls1, size * sizeof (*yylsp), &yystacksize); #else yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yystacksize); #endif yyss = yyss1; yyvs = yyvs1; #ifdef YYLSP_NEEDED yyls = yyls1; #endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp)); yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp)); #ifdef YYLSP_NEEDED yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp)); #endif #endif /* no yyoverflow */ yyssp = yyss + size - 1; yyvsp = yyvs + size - 1; #ifdef YYLSP_NEEDED yylsp = yyls + size - 1; #endif #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Stack size increased to %d\n", yystacksize); #endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Entering state %d\n", yystate); #endif goto yybackup; yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Reading a token: "); #endif yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Now at end of input.\n"); #endif } else { yychar1 = YYTRANSLATE(yychar); #if YYDEBUG != 0 if (yydebug) { fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ #ifdef YYPRINT YYPRINT (stderr, yychar, yylval); #endif fprintf (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); #endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif /* count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* Do the default action for the current state. */ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; /* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: yylen = yyr2[yyn]; if (yylen > 0) yyval = yyvsp[1-yylen]; /* implement default value of the action */ #if YYDEBUG != 0 if (yydebug) { int i; fprintf (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) fprintf (stderr, "%s ", yytname[yyrhs[i]]); fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 1: #line 136 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 2: #line 137 "gcl.y" { rest=yyval= join( join( yyvsp[-1], create(force)), yyvsp[0]); ; break;} case 3: #line 146 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(force)), yyvsp[-1]), create(force)), yyvsp[0]); ; break;} case 4: #line 159 "gcl.y" { rest=yyval= join( join( yyvsp[-1], create(force)), yyvsp[0]); ; break;} case 5: #line 168 "gcl.y" { rest=yyval= join( join( join( yyvsp[-2], yyvsp[-1]), create(force)), yyvsp[0]); ; break;} case 6: #line 179 "gcl.y" { rest=yyval= join( join( join( join( join( yyvsp[-3], create(force)), yyvsp[-2]), yyvsp[-1]), create(force)), yyvsp[0]); ; break;} case 7: #line 196 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 8: #line 197 "gcl.y" { rest=yyval= join( join( yyvsp[-1], create(force)), yyvsp[0]); ; break;} case 9: #line 208 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 10: #line 209 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 11: #line 210 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 12: #line 211 "gcl.y" { rest=yyval= join( join( join( join( join( join( yyvsp[-5], create(" ")), yyvsp[-4]), yyvsp[-3]), yyvsp[-2]), yyvsp[-1]), yyvsp[0]); ; break;} case 13: #line 228 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 14: #line 229 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 15: #line 230 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 16: #line 231 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 17: #line 234 "gcl.y" { rest=yyval= join( join( join( join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(" ")), create(indent)), create(opt5)), create(outdent)), yyvsp[0]); ; break;} case 18: #line 255 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 19: #line 256 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], yyvsp[-1]), create(" ")), create(opt9)), yyvsp[0]); ; break;} case 20: #line 271 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 21: #line 272 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 22: #line 273 "gcl.y" {rest=yyval=join(yyvsp[-2],join(yyvsp[-1],yyvsp[0]));; break;} case 23: #line 276 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 24: #line 277 "gcl.y" {rest=yyval=join(yyvsp[-2],join(yyvsp[-1],yyvsp[0]));; break;} case 25: #line 278 "gcl.y" {rest=yyval=join(yyvsp[-1],yyvsp[0]);; break;} case 26: #line 279 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(" ")), yyvsp[0]); ; break;} case 27: #line 294 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 28: #line 295 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 29: #line 298 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 30: #line 299 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 31: #line 302 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(force)), yyvsp[0]); ; break;} case 32: #line 317 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(force)), yyvsp[0]); ; break;} case 33: #line 332 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 34: #line 333 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(force)), yyvsp[-1]), create(" ")), yyvsp[0]); ; break;} case 35: #line 348 "gcl.y" { rest=yyval= join( join( join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(indent)), create(force)), yyvsp[0]), create(outdent)); ; break;} case 36: #line 367 "gcl.y" { rest=yyval= join( join( join( join( join( join( join( join( yyvsp[-3], create(indent)), create(force)), yyvsp[-2]), create(force)), yyvsp[-1]), create(outdent)), create(force)), yyvsp[0]); ; break;} case 37: #line 390 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 38: #line 391 "gcl.y" {rest=yyval=join(yyvsp[-1],yyvsp[0]);; break;} case 39: #line 394 "gcl.y" { rest=yyval= join( join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(" ")), yyvsp[0]), create(force)); ; break;} case 40: #line 411 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 41: #line 412 "gcl.y" { rest=yyval= join( join( join( yyvsp[-2], yyvsp[-1]), create(" ")), yyvsp[0]); ; break;} case 42: #line 425 "gcl.y" { rest=yyval= join( join( join( join( yyvsp[-2], create(" ")), yyvsp[-1]), create(" ")), yyvsp[0]); ; break;} case 43: #line 440 "gcl.y" {rest=yyval=yyvsp[0];; break;} case 44: #line 441 "gcl.y" { rest=yyval= join( join( join( join( join( join( yyvsp[-3], create(" ")), yyvsp[-2]), create(" ")), yyvsp[-1]), create(" ")), yyvsp[0]); ; break;} case 45: #line 460 "gcl.y" {rest=yyval=join(yyvsp[-4],join(yyvsp[-3],join(yyvsp[-2],join(yyvsp[-1],yyvsp[0]))));; break;} } /* the action file gets copied in in place of this dollarsign */ #line 498 "/usr/local/gnu/lib/bison.simple" yyvsp -= yylen; yyssp -= yylen; #ifdef YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; #ifdef YYLSP_NEEDED yylsp++; if (yylen == 0) { yylsp->first_line = yylloc.first_line; yylsp->first_column = yylloc.first_column; yylsp->last_line = (yylsp-1)->last_line; yylsp->last_column = (yylsp-1)->last_column; yylsp->text = 0; } else { yylsp->last_line = (yylsp+yylen-1)->last_line; yylsp->last_column = (yylsp+yylen-1)->last_column; } #endif /* Now "shift" the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; yyerrlab: /* here on detecting error */ if (! yyerrstatus) /* If not already recovering from an error, report this error. */ { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { int size = 0; char *msg; int x, count; count = 0; /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) size += strlen(yytname[x]) + 15, count++; msg = (char *) malloc(size + 15); if (msg != 0) { strcpy(msg, "parse error"); if (count < 5) { count = 0; for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) { strcat(msg, count == 0 ? ", expecting `" : " or `"); strcat(msg, yytname[x]); strcat(msg, "'"); count++; } } yyerror(msg); free(msg); } else yyerror ("parse error; also virtual memory exceeded"); } else #endif /* YYERROR_VERBOSE */ yyerror("parse error"); } goto yyerrlab1; yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); #endif yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; yyerrdefault: /* current state does not do anything special for the error token. */ #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault; #endif yyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #ifdef YYLSP_NEEDED yylsp--; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, "); #endif *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; } #line 463 "gcl.y" /************************************************* * additional pretzel code starts here: * *************************************************/ #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif PPARSE_NAME::PPARSE_NAME() { } PPARSE_NAME::~PPARSE_NAME() { static_scanner = NULL; } int PPARSE_NAME::prettyprint(istream* is, ostream* os) { Latex_cweb_output ppoutput(*os); return(prettyprint(is, &ppoutput)); } int PPARSE_NAME::prettyprint(istream* is, Output* outp) { int ret_val = 0; PSCAN_NAME ppscanner(is); static_scanner = &ppscanner; ret_val=yyparse(); while (!(is->eof())) { char c; is->get(c); } rest->print(*outp); return(ret_val); } void PPARSE_NAME::debug_on() { yydebug = 1; } void PPARSE_NAME::debug_off() { yydebug = 0; } /* This is a routine to print the semantic value */ static void yyprint(FILE *file, int type, YYSTYPE value) { Latex_cweb_output os(cerr); value->print(os); } /************************************************* * optional user defined C code follows here: * *************************************************/ pretzel-2.0n-2/contrib/aj/gcl.tab.o0000644000000000000000000007554406537754174015640 0ustar rootrootELFxä4(.shstrtab.text.rodata.data.ctors.bss.stab.stabstr.symtab.strtab.rela.text.rela.rodata.rela.ctors.rela.stab.commentã¿ð' D€ `’ Ô D@° €Çàèã¿ð' DÐ`’ Ð’@ Ô—* •:àÖ`’€ Ô  Ò DŸÂ€°€Çàè㺨À'¿è¾XÐ'»4»8Ð'»0 ÈÐ'»,Ò €¢`€`’ @  À'¿ìÀ'» ?þÐ'»(л4¤?þæ»0¤ à2л,’‘*`Ò»4 ’?þ€¤€ €|л0Ð'»Ð»4Ð'»Ò»4$€ ’‘:`’ Ò'» л, ’£€¢ € `@° €Yл,’‘*`Ð'»,л, ’£€¢ € cÐ'»,л,’•*` ” \’"€ ’ ‘2`’‘*`œ#€ \’ ‘2`’‘*`Ð'»4л4Ò»Ô» – •*à@л,’•*` ” \’"€ ’ ‘2`’‘*`œ#€ \’ ‘2`’‘*`Ð'»0л0Ò»Ô» – •*à@л ’‘*`Ò»4¤ ¤¿þл ’‘*`Ò»0¦ ¦ÿüÒ €¢`€ `’ Ô»,@л,’‘*`Ò»4 ’?þ€¤€ €° €öÒ €¢`€ `’ ”@€’‘*`’ Ð “* £:`?ÿà€¤@€€´Ð»(€¢?þ€Ò €¢`€`’ @’»$ ÿÿÐ'»(л(€¢ €À'¿èÀ'»(Ò €¢`€`’ @€/л(€¢!€ `Ò»( Ò •*`‘: € 4Ð'¿èÒ €¢`€Ð¿è’—*`˜ `’ Ô»(ÖÀ @`Ò»(Ô»$@`’ @пè¢@€¤`€€¤`g€’‘*`’ Ð “* ‘:`ҿ耢 €€€I’‘*`’ Ð “* £:`€¤`€ ?ÿà€¤@€€¡¢ €B€€¤`€€—€¤`U€° €PÒ €¢`€Ð¿è’—*`˜ `’ Ô»(ÖÀ @л(€¢ €?þÐ'»(¦àÒ»$Ò"п쀢 €Ò¿ìÿ’Ò'¿ì ¿þ¯’‘*`’ Ð “* £:`€¤`€€^’‘*`’ Ð “* ‘:`Ð'»Ð»€¢ €  Ò»" ’‘*`ÒÀÒ'»Ò €¢`€P’‘*`’ Ð “* —:``’ ”@’‘*`’ Ð “* ‘:`Ð'» л ’‘*`’ Ð “* ‘:`€¢ €€Ð» ’‘*`’ Ð “* ‘:`’•*`– `’ Ô€ @Ò» `’Ò'» ¿ÿÜ’‘*`’ Ð “* ‘:`’•*`– `’ Ô€ @ÿ€¢ ,€ˆ’‘*`’ Ð ÂÒÀÒ'»Ò" €N) @’Ðÿü@’ ÒÀ@Ð'»Ð»Ð% €<) @’Ðÿø@’ Òÿü@ª @’@’ ÒÀ@Ð'»Ð»Ð% €) @’Ðÿü@’ ÒÀ@Ð'»Ð»Ð% € )ÐÿøÒÿü@ª @’@’ ÒÀ@Ð'»Ð»Ð% €ô) @’Ðÿô@’ Òÿø@’ Òÿü@ª @’@’ ÒÀ@Ð'»Ð»Ð% €ÐÒÀÒ'»Ò" €Ê) @’Ðÿü@’ ÒÀ@Ð'»Ð»Ð% €¸ÒÀÒ'»Ò" €²ÒÀÒ'»Ò" €¬ÒÀÒ'»Ò" €¦)`@’Ðÿì@’ Òÿð@’ Òÿô@’ Òÿø@’ Òÿü@’ ÒÀ@Ð'»Ð»Ð% €ÒÀÒ'»Ò" €yÒÀÒ'»Ò" €sÒÀÒ'»Ò" €mÒÀÒ'»Ò" €g)`@’Ðÿø@’ Òÿü@ª`@’@ª @’@ª @’@ª @’@’ ÒÀ@Ð'»Ð»Ð% €.ÒÀÒ'»Ò" €()ÐÿøÒÿü@ª`@’@ª @’@’ ÒÀ@Ð'»Ð»Ð% €ÒÀÒ'»Ò" €ÒÀÒ'»Ò" €ü)ÐÿüÒÀ@’Ðÿø@Ð'»Ð»Ð% €îÒÀÒ'»Ò" €è)ÐÿüÒÀ@’Ðÿø@Ð'»Ð»Ð% €Ú)ÐÿüÒÀ@Ð'»Ð»Ð% €Ð)`@’Ðÿø@’ Òÿü@ª`@’@’ ÒÀ@Ð'»Ð»Ð% €¯ÒÀÒ'»Ò" €©ÒÀÒ'»Ò" €£ÒÀÒ'»Ò" €ÒÀÒ'»Ò" €—)`@’Ðÿø@’ Òÿü@ª @’@’ ÒÀ@Ð'»Ð»Ð% €w)`@’Ðÿø@’ Òÿü@ª @’@’ ÒÀ@Ð'»Ð»Ð% €WÒÀÒ'»Ò" €Q) @’Ðÿø@’ Òÿü@ª`@’@’ ÒÀ@Ð'»Ð»Ð% €1)`@’Ðÿø@’ Òÿü@ª @’@ª @’@’ ÒÀ@ª @’@Ð'»Ð»Ð% €) @’Ðÿô@ª @’@’ Òÿø@ª @’@’ Òÿü@ª @’@ª @’@’ ÒÀ@Ð'»Ð»Ð% €ÅÒÀÒ'»Ò" €¿)ÐÿüÒÀ@Ð'»Ð»Ð% €µ)`@’Ðÿø@’ Òÿü@ª`@’@’ ÒÀ@ª @’@Ð'»Ð»Ð% €ŒÒÀÒ'»Ò" €†)ÐÿøÒÿü@ª`@’@’ ÒÀ@Ð'»Ð»Ð% €n)`@’Ðÿø@’ Òÿü@ª`@’@’ ÒÀ@Ð'»Ð»Ð% €MÒÀÒ'»Ò" €G)`@’Ðÿô@’ Òÿø@ª`@’@’ Òÿü@ª`@’@’ ÒÀ@Ð'»Ð»Ð% €)ÐÿüÒÀ@’Ðÿø@’Ðÿô@’Ðÿð@Ð'»Ð»Ð% €Ð»’‘*`¦$Àл’‘*`¤$€Ò €¢`€&л4’?þÒ'» `’ @л €¢€€Ò» `’Ò'» Ð@“* •:``’à@¿ÿí`’ @¦àÒ»Ò"’‘*`’ Ð “* £:`’‘*`’ Ð “* ¡:`Ѐ“* ‘:` €¤ €€¤ g€’‘*`’ Ð “* ‘:`Ò€•*`“: €¢ € ’‘*`’ Ð “* ¡:`€ ’‘*`’ Ð “* ¡:`¿úGп쀢 € Ò» `’Ò'» `@€Ð¿ì€¢ €Ð»(€¢ €° €¨Ò €¢`€Ð¿è’—*`˜ `’ Ô»(ÖÀ @?þÐ'»( Ð'¿ì€8л4€¤€€° €‰¦ÿü¤¿þÒ‘*`¡: Ò €¢`€&л4’?þÒ'» `’ @л €¢€€Ò» `’Ò'» Ð@“* •:``’à@¿ÿí`’ @’‘*`’ Ð “* £:`?ÿà€¤@€¿ÿ¿¢`€¤`€€¤`g€’‘*`’ Ð “* ‘:`€¢ €€¿ÿª’‘*`’ Ð “* £:`€¤`€ ?ÿà€¤@€¿ÿš¢ ¿û €€¤`€¿ÿ€¤`U€° €Ò €¢`€`’ @¦àÒ»$Ò" ¿ùŒ€€Çàèã¿ @`Ð$°€Çàèã¿ ò' H`Ð$À" Ò H@Çàèã¿` ò' Hô' L’¿À Ò L@ Ô’  Ò—*`•:à’ ”¿ÀÖ  Ò HŸÂÀ¢’¿À ’ @°€Çàèã¿€ ò' Hô' LÀ'¿ì’¿è Ò H@’¿èÒ" @Ð'¿ìÒ HÐ@@€¢ €€’¿çРH@¿ÿóÐ`’ Ð’@ Ô—* •:àÖ`’€ Ô  Ò LŸÂ€â¿ì’¿è ’ @°€Çàèã¿” Ô"`Çàèã¿À"`Çàèã¿`ð' Dò' Hô' L’¿À ’ @РL’ Ð’@ Ò•*`“: Ô L’@ ”¿ÀÖ  ’ ŸÂÀ’¿À ’ @Çàèã¿ @Ð"`Çàèã¿¢ `Ð$@ €¢ €@€Çàèã¿’ Ò"°€Çàè%sStarting parse parser stack overflowStack size increased to %d Entering state %d Reading a token: Now at end of input. Next token is %d (%s) Shifting token %d (%s), Reducing via rule %d (line %d), %s -> %s state stack now %d parse errorDiscarding token %d (%s). Error: state stack nowShifting error token,     ')+-/359;=ACGJNPRTVZ^`dhmorvx|€‚‡#"#"#"#"#!"#!"*)-& & &$% %'' % '& &&'('++,, +' !.!//.011 0%23''ˆ‰’Ÿ¨³ÄÅÐÑÒÓäåæçêÿ&'*+.=LM\o†‡Š›œ©¸¹Ì$error$undefined.PREDICATECHUNKSEMIOPENCLOSEDOTDOTDOTBECOMESBLOCKCOMMAARROWCOLONSKIPABORTARRAYOFDOODIFFISWAPOPENBLOCKCLOSEBLOCKUNARY_OPMINUSBINARY_OPACCESSTYPEIDNUMBERstmt_listpredicatestmtassignexpr_listsimple_exprexprbinary_oprepetitionselectionguarded_listguarded_stmtblockdeclsdecltype_declstype_decltypebounds!!!!!!""########$%%&&&''''((ÿÿÿÿ)*++,-../001223  !% (&#"'$+*) ,-4 * 23HL/€ÿÿ€€ÿÿÿÿÿï€G €€5€€€€)€0ÿÿ/ÿï€ /€ÿÿÿÿ€€ÿÿ€/€ÿÿ€.84,€€/€€€€ÿú€€Aÿü€ÿÿ€€L€€€€ÿÿB7ÿÿ€€SX€ N€ÿíÿþÿý€€€ÿû€€9€€€€S+!1F$7:;()%& G()O 6" -9R<,>/8=?1().()D0()@AB'JC M EQ ()KTNPU5# I  &'  "  $* ..#,0B 7  EK O   ÿÿBÿÿÿÿÿÿÿÿ ék <dOdY€{€€´€Í€ë€/€s€‘€³€Ѐì€þ€€*€=€I€r€Í€á€ë€õ€‰¥€ ³€ ¿€ Ì€ Ø€ ä€ñ€ÿ€ €€'€6€C€P€\€ k€!y€"†€#•€'£€)²€*À€+Ï€,Ý€-ì€0ú€1 €G€H#€I1€K?€LM€ƒ€†Õ€Ž÷€€§³€Ìé€" €# ,€$ P€á €Ç Å€ ¹$g Ê gD Ó„DgDgDiDj,Dk8Àà8 Ù€ ‡€ A&{ T$} l }DD}D}D~DXÀàX {$Û Š„DÛDÛDáDæDçDóD D4D LD PD TD XD`DhDlD xD!œD$œD%¤D+¬DEÄDGÜDHìDJøDKDL DM,DNtDODPØDWôDX D^$D_8DbTDcxDg„Dh˜Dk´Dt¼DuØDvèD}ðD€DDƒ,Dˆ@DŠPD‹TDŽXDlD”ŒD—ÈD™ÜDDŸ(D¤@D¥HD¦”D¨œD±¸D³ÄD´ÔDµÜD¶àD¸ðD¹üD»D¼DÁDÂ0DÆdDÇtDÉ|DÏŒDѬDÒ°D׸DØÔDÙàDÝèDÞDßDâ4DãHDçHDê€DëÔDì8Dñ€ ª„Dˆ`D‰pDxD’¸DœÀDŸ 4D¥ <D¨ |D° „D³ ØD¿ àD hDÄ pDÅ €DË ˆDÎ ÈDÐ ÐDÑ àDÒ øDÓ Dá Dä ¬Då ÄDæ ÜDç ôDè Dê Dú Dý ðDÿ øD D D ˆD D  D ¸D ðD øDD@DhD!pD$ìD&ôD'D(D*$D+4D,LD8TD;ÌD=ÔDGÔDJLDLTDMdDWlDZäD\ìDjìDm¤Do¬D¬D„”D†œD‡¬DˆÔDŠÜD–ÜD™xD›€DœD¤˜D§ðD©øD³øD¶tD¸|D¹ŒDÇ”DÊHDÌPDÍ  °„Dó¨Dô¸DúÈDûÜDüÜDýèDþDÿDTDlD|D˜DÄD D"4D$PD(XD+hDVxDYˆD\Da Db°De¼DfÐDiDo DqD~D8D€<D†PD‡dDˆdD‰pDŠˆD‹ DŒÜD’ôD“D” D–(D—,D˜tDš|D›˜D¤Dž´DŸ¼D ÀD¢ÐD£ÜD¥äD¦ðD©üDªD­(D²8D³<D´T Ð@Ü Û@Ý â@Þ ï@ß ù€àÿÿÿì€áÿÿÿè€ãÿÿþX&€äÿÿû8<€æÿÿû4D€çÿÿû0L€óÿÿû,Z€öÿÿû(c€÷ÿÿû$m€øÿÿû w€þÿÿû€€ÿÿûÀÀxˆ€$ÿÿû‘€%ÿÿûš€+ÿÿû Àœà„à„À4¡€äÿÿû ÀHà€à€ÀÈ¥€üÿÿû ÀÜàlàlÀP­€ˆÿÿû ÀdàôàôàDµ€Ô$Ùä@Ùî„DÙDÙDÚ,À à ô$Ü@Ü ÜHDÜDÜDÝDÞ0Àà $àF@àP àH\ àLDàDàDáDâ$Dã€h€áÿÿÿÀÀÀ`àtà€t$åž@娠åH° åLDåDåDæDçDè(Dé4Dê@DìdDî|DïÀDðä¾€æÿÿÿìÈ€çÿÿÿèÀà€ëÿÿÿçÀ@àtÀÄàØàää$òû@òDòDòDòÀà$ó@óDóDóDóÀà'$÷H ÷DQ ÷HY ÷LD÷D÷DøDù(Dú|c€øÿÿÿÀÀà|i$þDþDqDqÀà†& • ¦&¶$ Å@ Î@ Û„D D D <Àà$ @ D D D Àà(q%&”B&µY&½p&ш&Ý¡&ç¶&ïË&÷ä&þ&&-&F&+_ jdgcl.tab.cgcc2_compiled./a/local/isasun29/1/mitarb/felix/pretzel/contrib/aj/gcl.tab.cint:t1=r1;-2147483648;2147483647;char:t2=r2;0;127;long int:t3=r1;-2147483648;2147483647;unsigned int:t4=r1;0;-1;long unsigned int:t5=r1;0;-1;long long int:t6=r1;01000000000000000000000;0777777777777777777777;long long unsigned int:t7=r1;0000000000000;01777777777777777777777;short int:t8=r1;-32768;32767;short unsigned int:t9=r1;0;65535;signed char:t10=r1;-128;127;unsigned char:t11=r1;0;255;float:t12=r1;4;0;double:t13=r1;8;0;long double:t14=r1;16;0;bool:t15=@s32;-16;void:t16=16__wchar_t:t17=r1;-2147483648;2147483647;__vtbl_ptr_type:T18=s8__delta:8,0,16;__index:8,16,16;__pfn:19=*16,32,32;__delta2:8,32,16;;__vtbl_ptr_type:t18size_t:t4fpos_t:t3FILE:t20=s16_cnt:1,0,32;_ptr:21=*11,32,32;_base:21,64,32;_flag:11,96,8;_file:11,104,8;._0::22=##23=*20;:__3._0;2A.24=##23;:__3._0RC3._0;2A.;__as::25=##26=&20;:3._0RC3._0;2A.;;_G_clock_t:t3_G_dev_t:t5_G_fpos_t:t3_G_gid_t:t3_G_ino_t:t5_G_mode_t:t5_G_nlink_t:t5_G_off_t:t3_G_pid_t:t3_G_ptrdiff_t:t1_G_sigset_t:t1_G_size_t:t4_G_time_t:t3_G_uid_t:t3_G_wchar_t:t17_G_ssize_t:t1_G_wint_t:t3_G_va_list:t19_G_int8_t:t10_G_uint8_t:t11_G_int16_t:t8_G_uint16_t:t9_G_int32_t:t3_G_uint32_t:t5_G_int64_t:t6_G_uint64_t:t7streamoff:t3streampos:t3streamsize:t1__fmtflags:t5__iostate:t11io_state:t27=ebadbit:4,failbit:2,eofbit:1,goodbit:0,;open_mode:t28=ebin:128,noreplace:64,nocreate:32,trunc:16,app:8,ate:4,out:2,in:1,;seek_dir:t29=eend:2,cur:1,beg:0,;_seek_dir:t29_IO_marker:Tt30=s12_next:31=*30,0,32;_sbuf:32=*33=xs_IO_FILE:,32,32;_pos:1,64,32;_IO_marker::34=##31;:;2A.35=##31;:RC10_IO_marker;2A.;__as::36=##37=&30;:RC10_IO_marker;2A.;;_IO_FILE:Tt33=s76_flags:1,0,32;_IO_read_ptr:38=*2,32,32;_IO_read_end:38,64,32;_IO_read_base:38,96,32;_IO_write_base:38,128,32;_IO_write_ptr:38,160,32;_IO_write_end:38,192,32;_IO_buf_base:38,224,32;_IO_buf_end:38,256,32;_IO_save_base:38,288,32;_IO_backup_base:38,320,32;_IO_save_end:38,352,32;_markers:31,384,32;_chain:32,416,32;_jumps:39=*40=xs_IO_jump_t:,448,32;_fileno:1,480,32;_blksize:1,512,32;_offset:3,544,32;_cur_column:9,576,16;_unused:2,592,8;_shortbuf:41=ar1;0;0;2,600,8;_IO_FILE::42=##32;:;2A.43=##32;:RC8_IO_FILE;2A.;__as::44=##45=&33;:RC8_IO_FILE;2A.;;__manip:t46=*47=f48=&49=xsios:__imanip:t50=*51=f52=&53=xsistream:__omanip:t54=*55=f56=&57=xsostream:Format_command:t58=ecancel:18,no_indent:17,big_force:16,force:15,break_space:14,backup:13,opt9:12,opt8:11,opt7:10,opt6:9,opt5:8,opt4:7,opt3:6,opt2:5,opt1:4,opt0:3,outdent:2,indent:1,null:0,;Latex_cweb_output:Tt59=s44!1,020,60=xsOutput:;Latex_cweb_output::61=#59,16,62=*59,1,16;:_._17Latex_cweb_output;2A*1;60;63=##62;:R7ostream;2A.;flush_output::64=##16;:;0A*2;60;;;~%60;Pparse:Tt65=s4.vf65:66=*67=ar1;0;2;18,0;Pparse::68=#65,16,69=*65,1,16;:_._6Pparse;2A.70=##69;:;2A.71=##69;:RC6Pparse;2A.;__as::72=##73=&65;:RC6Pparse;2A.;prettyprint::74=##1;:P7istreamP7ostream;2A*1;65;75=##1;:P7istreamP6Output;2A*2;65;;;~%65;yyerror__FPCc:F1s:p76=*2gcl.yAttribute:Tt77=s4.vf77:78=*79=ar1;0;1;18,0;Attribute::80=##81=*77;:;2A.82=##81;:RC9Attribute;2A.;__as::83=##84=&77;:RC9Attribute;2A.;print::85=##16;:R6Output;2A*1;77;;;~%77;Pscan:Tt86=s4.vf86:78,0;Pscan::87=#86,16,88=*86,1,16;:_._5Pscan;2A.89=##88;:P7istream;2A.90=##88;:RC5Pscan;2A.;__as::91=##92=&86;:RC5Pscan;2A.;scan::93=##1;:PP9Attribute;2A*1;86;;;~%86;static_scanner:S88yylex__FPP9Attribute:f1rvalue:p94=*81yyparse__Fv:F1/usr/local/gnu/lib/bison.simplegcl.y/usr/local/gnu/lib/bison.simpleyystate:r1yyn:r1yyssp:r95=*8yyvsp:r94yyerrstatus:1yychar1:1yyssa:96=ar1;0;199;8yyvsa:97=ar1;0;199;81yyss:95yyvs:94yystacksize:1yychar:1yylval:81yynerrs:1yyval:81yylen:1yyvs1:94yyss1:95size:1i:1ssp1:95ssp1:95Ppparse:Tt98=s4!1,020,65;Ppparse::99=#98,16,100=*98,1,16;:_._7Ppparse;2A.101=##100;:;2A.102=##100;:RC7Ppparse;2A.;__as::103=##104=&98;:RC7Ppparse;2A.;prettyprint::105=##1;:P7istreamP7ostream;2A*1;65;106=##1;:P7istreamP6Output;2A*2;65;;debug_on::107=##16;:;2A.;debug_off::107:;2A.;;~%65;__7Ppparse:F100this:P100gcl.y_._7Ppparse:F16this:P100__in_chrg:p1prettyprint__7PpparseP7istreamP7ostream:F1this:P100is:p108=*53os:p109=*57ppoutput:59prettyprint__7PpparseP7istreamP6Output:F1this:P100is:p108outp:p110=*60ret_val:1ppscanner:111=xsPpscan:c:2debug_on__7Ppparse:F16this:P100debug_off__7Ppparse:F16this:P100yyprint__FP4FILEiP9Attribute:f16file:p23type:p1value:p81os:59_GLOBAL_.I.yyerror__FPCc:F16_vt.5Pscan:S79_vt.7Ppparse:G67_vt.6Pparse:S67_._6Pparse:F16this:P69__in_chrg:P1/users/felix/lib/pretzel/include/Pparse.h__6Pparse:F69this:P69rest:S81yytranslate:S112=ar1;0;287;2yyprhs:S113=ar1;0;45;8yyrhs:S114=ar1;0;140;8yyrline:S115=ar1;0;45;8yytname:S116=ar1;0;52;76yyr1:S117=ar1;0;45;8yyr2:S118=ar1;0;45;8yydefact:S119=ar1;0;85;8yydefgoto:S120=ar1;0;18;8yypact:S121=ar1;0;85;8yypgoto:S122=ar1;0;18;8yytable:S123=ar1;0;103;8yycheck:S124=ar1;0;103;8yydebug:G1ÿñÿñ n\ (ÐøÔ# øÐ+ &3À?Ø KÌ\P(\U„¬^Td 0&n@`ƒˆø\ V¬–˜¡°„ÍÕÝ \éü4ô08-¨:Obð쉔 ¢ÜµÀÅ@Óhˆû *28Røfwø("´D"Œ—gcl.tab.cyyrlineyytableyytnameyycheckyypgoto_vt.6Pparseyytranslateyyr1yyr2yydefactyyrhsyydefgotoyylex__FPP9Attributerestyyprhsyypact_vt.5Pscanstatic_scanneryyprint__FP4FILEiP9Attribute_Q_qtodyydebugyyparse__Fv__7Ppparse_._7Ppparsememcpy_._17Latex_cweb_output__pure_virtual_vt.7Ppparsejoin__FP9AttributeT0__6PpscanP7istreamprettyprint__7PpparseP7istreamP6Output_GLOBAL_.I.yyerror__FPCcdebug_on__7Ppparseeof__C3ioscerryyerror__FPCcprettyprint__7PpparseP7istreamP7ostreamget__7istreamRc__17Latex_cweb_outputR7ostreamfprintf__iobcreate__F14Format_commanddebug_off__7Ppparse__builtin_delete__6Pparse_._6Pparse_._6Ppscancreate__FPc1 1   $0H L ` p À Ä Ô1 Ø1 Ü à ä0| € „,(!Œ!Ä È Ø1 Ü1 à 0ä 0ì0$ ( 81 <1 @ PD PL0d Vh V  ¤ ´1 ¸1 ¼ hÀ hÄ0ø ü  1 1  € €0< Ø@ Øh l ˆ øŒ ø1 ”1 ˜ ˜œ ˜¨0°1 ´1 È1 Ì1 Ð °Ô °Ø0 ø  øD (H (¼ À Ü øà øä1 è1 ì ¸ð ¸ü0` „d „ (” (Ô Ø ð nô n1 1   Ø Ø0( ø, øL TP T€ T„ Tœ ø  ø¤1 ¨1 ¬ ° ¸0à Ìä Ìü ø ø1 1    08 L< LL P T `X Ü\ $` €d h (l pp ˆt  x ¸| T€ l„ „ˆ œŒ ´ ˜” °˜0œH `¤˜¨°¬è°´”¸¬¼ÄÀÜÄôÈtÌôÐ ÔŒØLÜ<àTä|è ì8ð˜ôø4üð    2 0% D% T ` h2 x% Œ% œ2 ¬% À% Ð Ü ä2 ô% %  $ 0% @2 P% d% t € ˆ2 ˜% ¬% À% Ð2 à% ô%    ( 02 @% T% d p | ˆ ”   ¬ ¸ ¼  À  Ä8 Ô% è% ü% % $% 8% H T ` l x „  œ ¨ ´ ¸  ¼  À8 Ð% ä% ð  ô  ø8 % 2 (% 82 H% X2 h% |% Œ ˜ ¤ ° ¼% È  Ì  Ð8 à% ð2%%$ 0 < H T ` l%|%Œ ˜ ¤ ° ¼%Ì%Ü è ô%    8,%@%L P T8d%x%ˆ ”   ¬ ¸ Ä Ð Ü è ô ø ü 8%$%42D%X%h t x | €8%¤%´2Ä%Ø%è ô    2$%8%D H L8\%p%€ Œ  ” ˜8¨%¼%Ì2Ü%ì2ü%% 20%@ L T2d%t2„%˜%¨2¸%Ì%Ü2ì%ü2 % %0 < H T `%p | € „ ˆ8˜%¬%¸ ¼ À8Ð%ä%ô2%   , 8 D%P T X8h%|%Œ ˜ œ   ¤8´%È%Ô Ø Ü8ì%%  ( 4 8 < @8P%d%p t x8ˆ%œ%¨ ¬ °8À%Ô%ä ð ü% %%,%< h l ˆ1 Œ1  ” ˜0Ô1 Ø1 Ü (à (ä0ô1 ø1 ü 0 00$ Ì( Ì@ ÀD À„ øˆ ø¸ (¼ (Ü îà î 8 8 ,\ ` | ø€ ø„1 ˆ1 Œ H Hœ0ð ô 1 1  h h 0\1 `1 d (h (l0|1 €1 „ 0ˆ 0Œ0œ V  Vì øð ø$ (( (œ   °1 ´1 ¸ €¼ €À05$ $ <$ @$ H L X6„/Ô"&   $8*\.l p „ ” À7ä ì   (+ ,+ 0/„"œ2¤ ¨ À ÀÄ Àà4 À À¤#´-¼'Ì#Ô#øÐüØàð  ( 0$8(@,H0P4X8`<h@pDxH€LˆPT˜X \°`ÀdÐhØlèpðtøx|€„(ˆ0Œ8H”X˜`œp €¤¨ ¬°°¸´À¸È¼ØÀèÄð( ,D,\Ôà@@L  €HH`ü¨ -¼'Ü)03„(\˜tÀ€6¤´ì5@LØXødTpn|øˆÌ”( „¬ 0¸ VÄ Ð (Ü øô as: SC4.0 dev 15 Feb 1995 GCC: (GNU) 2.7.24‚ ¸ Ø È* *¨&*¬+*¬ø 1A¤k:U BX £J[Dä  Ut(¬  bvÔ  nvàÔ  yx´-pretzel-2.0n-2/contrib/aj/gcl.ft0000644000000000000000000000424006537722744015225 0ustar rootroot %{ char *typeset_pred(char *pred); %} %% "(" OPEN "[" OPEN ")" CLOSE "]" CLOSE ";" SEMI { ";" } ".." DOTDOT "." DOT "," COMMA { ", " } "##" BLOCK { "$[]$" } "-->" ARROW { "$\\longrightarrow$" } ":" COLON { " : " } ":=" BECOMES { "$\\leftarrow$" } "skip" SKIP { "\\underline{\\bf skip}" } "abort" ABORT { "\\underline{\\bf abort}" } "array" ARRAY { "{\\bf array}" } "of" OF { "{\\bf of}" } "do" DO { "\\underline{\\bf do}" } "od" OD { "\\underline{\\bf od}" } "if" IF { "\\underline{\\bf if}" } "fi" FI { "\\underline{\\bf fi}" } "|[" OPENBLOCK { "$|[$" } "]|" CLOSEBLOCK { "$]|$" } "!" UNARY_OP { "$\\neg$" } "~" UNARY_OP { "$\\neg$" } "-" MINUS "<" BINARY_OP { "$<$" } ">" BINARY_OP { "$>$" } "<=" BINARY_OP { "$\\leq$" } ">=" BINARY_OP { "$\\geq$" } "+" BINARY_OP "*" BINARY_OP { "$\\times$" } "/" BINARY_OP { "\\underline{\\bf div}" } "div" BINARY_OP { "\\underline{\\bf div}" } "%" BINARY_OP { "\\underline{\\bf mod}" } "mod" BINARY_OP { "\\underline{\\bf mod}" } "=" BINARY_OP { "$=$" } "==" BINARY_OP { "$=$" } "!=" BINARY_OP { "$\\neq$" } "/=" BINARY_OP { "$\\neq$" } "max" BINARY_OP { "\\underline{\\bf max}" } "min" BINARY_OP { "\\underline{\\bf min}" } "var" ACCESS { "\\underline{\\bf var}" } "con" ACCESS { "\\underline{\\bf con}" } "swap" SWAP { "\\underline{\\bf swap}" } "int" TYPE { "{\\bf integer}" } "integer" TYPE { "{\\bf integer}" } "bool" TYPE { "{\\bf boolean}" } "boolean" TYPE { "{\\bf boolean}" } [a-zA-Z]+ ID { "$\\mathit{" ** "}$" } [0-9][0-9]* NUMBER { "$" ** "$" } "{>".*"<}" PREDICATE { "$\\{" [create(typeset_pred(yytext))] " \\}$" } ^"@use\ ".* CHUNK { "\n" ** "\n" } [\t\ \n] pretzel-2.0n-2/contrib/aj/gcl.l0000644000000000000000000001757510765024470015053 0ustar rootroot/************************************************ * This is a flex file generated by pretzel * * * ************************************************/ %{ /* some needed headers: */ #include #include"attr.h" /* we'll define yywrap() which is needed for the scanner * here, so we won't have to bother about it if we're * doing the standard case. You can define your own version * by #undef'ing PSCAN_YYWRAP and supplying your own definition * in the definitions section. */ #define PSCAN_YYWRAP /* input will come from this istream */ static istream * yyin_stream; /* redefine YYINPUT to read from input streams */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } %} %{ char *typeset_pred(char *pred); %} /************************************************ * some pretzel definitions start here: * ***********************************************/ %{ /* the default name of the include file with the token * code definitions is stored in PTOKDEFS_NAME and * defaults to `ptokdefs'. */ #ifndef PTOKDEFS_NAME #define PTOKDEFS_NAME "ptokdefs.h" #endif /* now we have to include the token definitions */ #include PTOKDEFS_NAME /* allow user to choose generated scanner class name*/ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* redefine the interface of the scanner */ #undef YY_DECL #define YY_DECL int yylex (Attribute**rvalue) /* here's the standard version of yywrap() */ #ifdef PSCAN_YYWRAP extern "C" int yywrap() { return(1); } #endif %} %% "(" {*rvalue=create(yytext);return (OPEN);} "[" {*rvalue=create(yytext);return (OPEN);} ")" {*rvalue=create(yytext);return (CLOSE);} "]" {*rvalue=create(yytext);return (CLOSE);} ";" { *rvalue=join( create(";")); return(SEMI);} ".." {*rvalue=create(yytext);return (DOTDOT);} "." {*rvalue=create(yytext);return (DOT);} "," { *rvalue=join( create(", ")); return(COMMA);} "##" { *rvalue=join( create("$[]$")); return(BLOCK);} "-->" { *rvalue=join( create("$\\longrightarrow$")); return(ARROW);} ":" { *rvalue=join( create(" : ")); return(COLON);} ":=" { *rvalue=join( create("$\\leftarrow$")); return(BECOMES);} "skip" { *rvalue=join( create("\\underline{\\bf skip}")); return(SKIP);} "abort" { *rvalue=join( create("\\underline{\\bf abort}")); return(ABORT);} "array" { *rvalue=join( create("{\\bf array}")); return(ARRAY);} "of" { *rvalue=join( create("{\\bf of}")); return(OF);} "do" { *rvalue=join( create("\\underline{\\bf do}")); return(DO);} "od" { *rvalue=join( create("\\underline{\\bf od}")); return(OD);} "if" { *rvalue=join( create("\\underline{\\bf if}")); return(IF);} "fi" { *rvalue=join( create("\\underline{\\bf fi}")); return(FI);} "|[" { *rvalue=join( create("$|[$")); return(OPENBLOCK);} "]|" { *rvalue=join( create("$]|$")); return(CLOSEBLOCK);} "!" { *rvalue=join( create("$\\neg$")); return(UNARY_OP);} "~" { *rvalue=join( create("$\\neg$")); return(UNARY_OP);} "-" {*rvalue=create(yytext);return (MINUS);} "<" { *rvalue=join( create("$<$")); return(BINARY_OP);} ">" { *rvalue=join( create("$>$")); return(BINARY_OP);} "<=" { *rvalue=join( create("$\\leq$")); return(BINARY_OP);} ">=" { *rvalue=join( create("$\\geq$")); return(BINARY_OP);} "+" {*rvalue=create(yytext);return (BINARY_OP);} "*" { *rvalue=join( create("$\\times$")); return(BINARY_OP);} "/" { *rvalue=join( create("\\underline{\\bf div}")); return(BINARY_OP);} "div" { *rvalue=join( create("\\underline{\\bf div}")); return(BINARY_OP);} "%" { *rvalue=join( create("\\underline{\\bf mod}")); return(BINARY_OP);} "mod" { *rvalue=join( create("\\underline{\\bf mod}")); return(BINARY_OP);} "=" { *rvalue=join( create("$=$")); return(BINARY_OP);} "==" { *rvalue=join( create("$=$")); return(BINARY_OP);} "!=" { *rvalue=join( create("$\\neq$")); return(BINARY_OP);} "/=" { *rvalue=join( create("$\\neq$")); return(BINARY_OP);} "max" { *rvalue=join( create("\\underline{\\bf max}")); return(BINARY_OP);} "min" { *rvalue=join( create("\\underline{\\bf min}")); return(BINARY_OP);} "var" { *rvalue=join( create("\\underline{\\bf var}")); return(ACCESS);} "con" { *rvalue=join( create("\\underline{\\bf con}")); return(ACCESS);} "swap" { *rvalue=join( create("\\underline{\\bf swap}")); return(SWAP);} "int" { *rvalue=join( create("{\\bf integer}")); return(TYPE);} "integer" { *rvalue=join( create("{\\bf integer}")); return(TYPE);} "bool" { *rvalue=join( create("{\\bf boolean}")); return(TYPE);} "boolean" { *rvalue=join( create("{\\bf boolean}")); return(TYPE);} [a-zA-Z]+ { *rvalue=join( join( join( create("$\\mathit{"), create(yytext) ), create("}$") )); return(ID);} [0-9][0-9]* { *rvalue=join( join( join( create("$"), create(yytext) ), create("$") )); return(NUMBER);} "{>".*"<}" { *rvalue=join( join( join( create("$\\{"), create(typeset_pred(yytext)) ), create(" \\}$") )); return(PREDICATE);} ^"@use\ ".* { *rvalue=join( join( join( create("\n"), create(yytext) ), create("\n") )); return(CHUNK);} [\t\ \n] /* empty */ %% /************************************************ * additional pretzel C code follows here: * ***********************************************/ PSCAN_NAME::PSCAN_NAME (istream* is ) : Pscan(is) { yyin_stream = is; } PSCAN_NAME::scan(Attribute* *rvalue) { return(yylex(rvalue)); } PSCAN_NAME::~PSCAN_NAME () { yyrestart(NULL); } /************************************************ * additional user defined C code follows here: * ***********************************************/ pretzel-2.0n-2/contrib/aj/gcl.lex.o0000644000000000000000000015165406537754167015661 0ustar rootrootELFÑ|4(.shstrtab.text.data.rodata.bss.stab.stabstr.symtab.strtab.rela.text.rela.rodata.rela.stab.commentã¿° €Çàè㿈ð' DÒ €¢`€,À" Ò €¢`€’ Ò" Ò €¢`€’ Ò" Ò €¢`€’ Ò" Ò €¢`€ Ð`@Ð"`@€€Ìâ Ò Ò,@¤à Ð`Ò   Ô @’  ÿ” “* ”à’@ Ð `”“* ”àÒ@ •*`“: €¢`€à"`â"`”“* ”àÒ@ •*`“: ” ÿ’@ ” “* ”àÒ@ •*`“: €¢@€€”“* ”àÒ@ •*`¡: €¤ j€ ’ ÿ” “* ”à’@ Ð `¿ÿÚ”“* ”àÒ@ •*`“: ” ÿ’@ ” “* ”àÒ@ •*`¡: ¢`’‘*`’ Ð “* ‘:`€¢ ~€€¿ÿ¤’‘*`’ Ð “* §:`€¤à€ â à ’‘*`’ Ð “* §:`ä" ’$@Ò" Ò @Ò* À,@â" €¤à8€8’‘*`’ Ð ÂÒ Ò,@â à ¿ÿ–Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€Ý€ÕÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€¿€·Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€¡€™Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€ƒ€{Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€a€YÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€C€;Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€%€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°! €€ûÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°! €á€ÙÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°! €¿€·Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°! €€•Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°! €{€sÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€Y€QÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€7€/Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€€ Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€ó€ëÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€Ñ€ÉÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€¯€§Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€€…Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€k€cÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€I€AÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€'€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€€ýÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€ã€ÛÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€Å€½Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€£€›Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€€yÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€_€WÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€=€5Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð`@Ò DÐ"@°!€€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€ý€õÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€Û€ÓÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€¹€±Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€—€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€u€mÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€S€KÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€1€)Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€í€åÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€Ë€ÃÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€©€¡Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€‡€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€e€]Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€C€;Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€!€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€ÿ€÷Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€Ý€ÕÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@’ @Ò DÐ"@°!€»€³Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@¨Ð`@’@¨`@’@’ @Ò DÐ"@°!€‡€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@¨Ð`@’@¨`@’@’ @Ò DÐ"@°!€S€KÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@¨Ð`@’ @’@¨`@’@’ @Ò DÐ"@°!€€Ò €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" `@¨Ð`@’@¨`@’@’ @Ò DÐ"@°!€ç€ßÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" €ÊÒ €¢`€Ð`Ò Ôà’@ Ô ÿ—* “:à”` €  ’`?ÿÒ" Ð Ò`” Öà@€¬° €¯Ò $@ ’?ÿÒ'¿ìÒ Ò,@Ð`Ò $€¢`€Ò Ô`Ô" Ð`Ô`Ô"Ð`’ Ò" $Ò Ò`Ô ’@ Ð €¢ €(Ô`ҿ씀 Ô" @‚ @îÐ'¿èä п耢 €Ô`’ ” Ô" ¢ à¿è¿÷¨€â ¿ø€V@b€¢ €€¢ €€¢ €+€I€¢ €5€DÀ" @€¢ €Ô`Ô" Ò ¦ÿ‘<à“2 ”À ‘: ¦ 8¿÷ø€ Ò €¢`€Ð`@€"Ô`ҿ씀 Ô" @( â ä ¿÷]Ò Ò`Ô ’@ Ò" @ â ä ¿÷«€`@I¿÷4€€Çàèã¿xÐ`à â Ò Ö ”àÖ`’€ Ð €¢ €`@+Ð`Ò €¢`€Ð Ò`" €¢ €° €Ù€° €ÔÐ Ò`¤" ¤¿ÿ¦ €¤À€€ Ð @Ð,¢`  ¦à¿ÿöÐ`Ò $€¢`€ Ð`À"`À" €€Ð`Ò "@’?ÿÒ'¿èп耢 €€MÒ Ò'¿äÒ¿äÐ Ò`" Ð'¿àпäÒ €¢`€&пäÒ  “* Ò'¿Üп܀¢ € пäÒ¿äÔ¿äÖ  •2àÒ` ”@ Ô" €Ð¿äÒ¿äÔ` ’ •*`Ô" пäÒ¿äÔ` ’ Ð @ÓÒ¿äÐ"`€Ð¿äÀ" пäÒ €¢`€`@¬Ò¿äÔ`Ò¿à”€ Ô" Ð`Ò "@’?ÿÒ'¿è¿ÿ±Ð¿è€¢ €Ð'¿èÒ Ð@@€¢ €À" €Ò Ô`’€ Ð Ô¿è@)Ð`@Ð% Ð`Ô`Ô" Ò €¢`€€¤ €  Ð'¿ìÐ`@€ Ð'¿ìÐ`’ Ò" $€À'¿ìÔ`’€Ò" Ò Ð`Ò  À*Ð`Ò Ô @ À* Ò Ô`Ô" ð¿ì€Çàèã¿Ð ÔàÖ  Ò Ö €¢@ €€]Ö @™*à—; €¢à€ Ø @– ÿ˜ —+ ˜`–À Ô à€” ˜—+ ˜`ÖÀ ™*à—; €¢à€Ð"àÒ"à˜—+ ˜`ÖÀ ™*à—; ˜  ÿ–À ˜ —+ ˜`ÖÀ ™*à—; €¢À€€˜—+ ˜`ÖÀ ™*à‘; €¢ j€ –  ÿ˜ —+ ˜`–À Ô à¿ÿÚ˜—+ ˜`ÖÀ ™*à—; ˜  ÿ–À ˜ —+ ˜`ÖÀ ™*à‘; ’`¿ÿ °€Çàèã¿ð' DÒ ” Ö D˜ —+ ˜`ÖÀ ™*à—; €¢à€Ø DØ"àÒ"àÖ D˜ —+ ˜`ÖÀ ™*à—; ˜  ÿ–À ˜ —+ ˜`ÖÀ ™*à—; Ø D€¢À €€Ö D˜ —+ ˜`ÖÀ ™*à—; Ö' DÖ D€¢àj€ –  ÿ˜ —+ ˜`–À Ô à¿ÿÕÖ D˜ —+ ˜`ÖÀ ™*à—; ˜  ÿ–À ˜ —+ ˜`ÖÀ ™*à—; Ö' DÖ D˜àj€  `?ÿ€¢ €Ö D€– ° €Çàèã¿ð' D â Ò Ò,@Ð`Ò `€¤@€8Ò ¤`Ð`Ò Ô` ’ Ð ¦@Ð`Ò ¨€ Ð`Ò €¥ €€ ¦ÿÿ¨?ÿ’Ô @Ô*¿ÿò$À¢@$À Ð`ÔàÖ  Ö"`Ö" Ð`Ò `€¤@€`@'¢ÿÒ GÒ*à" Ò @Ò* â" Çàè㿈Ð`Ô `Ô*Ð`Ò •*`‘: €¢ €SÒ Ò`Ô ’@ Ð €¢ €Ð`À*€CÐ Ò`" Ð'¿èÔ`’ ” Ô" ÿý®€¢ €€¢ €€¢ €#€)€¢ €€$Ð`@@€¢ €°?ÿ€5Ò €¢`€Ð`@ÿÿ®°€'Ô`ҿ蔀 Ô" €Ð`Ò `ÿÐ'¿ìÐ`À*Ö ”à– Ö"`’ Ô @Ô* Ð`Ò¿ì”` €  ’`?ÿÒ" ð¿ì€Çàèã¿ð' DÒ €¢`€ Ð`@Ð"`Ð`Ò D@@Çàèã¿ð' DÒ Ð D€¢@€€Ò €¢`€Ð`Ô `Ô*Ð`Ô`Ô" Ð`Ô`Ô" Ò DÒ" @’ Ò" Çàèã¿Ò Ô`Ô" ÔàÖ Ö"`Ö" Ò Ô@Ô" Ò Ô @Ô* Çàè㿈ð' Dò' H (@LÐ'¿ìп쀢 €`@5пìÒ HÒ" пìÔ ’  @:Ò¿ìÐ"`пìÒ €¢`€`@!Ð¿ì’ Ò" пìÒ D@ð¿ì€Çàèã¿ð' DРD€¢ €€Ò DÐ €¢@€À" РDÒ €¢`€Ò DÐ`@ РD@Çàèã¿ð' Dò' HРD@РDÒ HÒ"РD’ Ò" à DРH€¢ €Ð H@’ @€¢ 4€  € Ð$ Çàèã¿ð' DРD€¢ €€Ð DÀ" РDÒ À*@РD’ Ô @ À*РDÒ DÔ`Ô" РD’ Ò" РDÀ" $Ò DÐ €¢@€@Çàè㿈ð' Dò' HРH€¢ €Ð HÒ D Ò ?þ•*`‘: €¢ € РHÒ D Ò ?ÿ•*`‘: €¢ €€° €. (@Ð'¿ìп쀢 €`@†Ð¿ìÒ H”þÔ" пìÒ¿ìÔ DÔ"`Ô" пìÀ" пìÀ"пìÒ¿ìÔ` Ô" пìÀ" Ð¿ì’ Ò" пìÀ" пìÀ" $пì@ð¿ì€Çàè㿈ð' DÀ'¿ìРDÒ¿ì Ò •*`‘: €¢ €€Ò¿ì`’Ò'¿ì¿ÿñРDÒ¿ì@°€Çàèã¿€ð' Dò' HРH’ Ò'¿äпä@LÐ'¿èп耢 €`@5À'¿àпàÒ H€¢ €€Ð¿èÒ¿à Ò DÔ¿à’@ Ô @Ô*Ò¿à`’Ò'¿à¿ÿíпèÒ H Ò HÔ¿è’@ À*`À*пèÒ¿ä@Ð'¿ìп쀢 €`@ Ð¿ì’ Ò" ð¿ì€Çàèã¿ð' D`’ Ô D@ @Çàèã¿ð' DРD@°€Çàèã¿ð' Dò' HРDÒ H@°€Çàèã¿ð' DРD@Çàèã¿ ò' HÒ H@`Ð$Ò HÒ" °€Çàèã¿ ò' HРH@°€Çàèã¿ ò' H`Ð$ @Ò H@Çàèã¿¢ `Ð$@ €¢ €@€Çàèã¿’”àÔ"@° €Çàè;, $[]$$\longrightarrow$ : $\leftarrow$\underline{\bf skip}\underline{\bf abort}{\bf array}{\bf of}\underline{\bf do}\underline{\bf od}\underline{\bf if}\underline{\bf fi}$|[$$]|$$\neg$$<$$>$$\leq$$\geq$$\times$\underline{\bf div}\underline{\bf mod}$=$$\neq$\underline{\bf max}\underline{\bf min}\underline{\bf var}\underline{\bf con}\underline{\bf swap}{\bf integer}{\bf boolean}$\mathit{}$$$\{ \}$ fatal flex scanner internal error--no action foundfatal flex scanner internal error--end of buffer missedfatal error - scanner input buffer overflowflex scanner push-back overflowout of dynamic memory in yy_create_buffer()out of dynamic memory in yy_scan_buffer()out of dynamic memory in yy_scan_bytes()bad buffer in yy_scan_bytes()%s 7656" 2 $11111111111666& '2 %1111111111111 111+!-()#11*11/1 ,31141140.  !"#$%&'()*+,-./0123g|~~gt~~~~~~ljcfa~`_^~@JIMSWS~?~~T~~X~~~~~A>??783;B=B1C~,~,9/3)(;%/",)4B+&~<WZjjjjjjjjjjjjjjjjjjjjjkjjkkkkkkkkkkjjjjjjjjjjjjjjkjkkkkkkkkkkkkkkkkkljjjkkkkkkkkkkkklljkkkkkkljkkkkmkkmkkjjj  !"#$%&48;=V@9A<B>2i5h?fedVCcba`_V]\[ZYXWV^UTUgSgRQPONMLKJI-HGFED:76310/.-,+*)(j'jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj V!!" kfe cb_^"[ZYXWUSRNKJIGEVlDlmCmB?>=<87654-*'%$#jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj’Œ <dOdY€{€€´€Í€ë€/€s€‘€³€Ѐì€þ€€*€=€I€r€Í€á€ë€õ€‰¥€#€ ¢€&#€3,€8€X€p€"{€‡€“€€¨€ ·€!€"Ë€#Ô€%߀&é€'ô€(ÿ€-#€61€7A€DM€E[€^g€ru€uƒ€‹€ˆ–€‰¡€Žª€›¶€œÁ€Ì€ž×€Ÿ䀠ú€¦ €§ €® €¯ !€° *€± 3€² <€¾ G€Ä Q€É \€Î i€Ó t€Ù €Ú ‰€Û ‘€Ü š€ ¦€ ±€ ¼€ Å€ Ï€ ဠ ü€¢ €À +€Æ 7€³ P€ê m€ò ˆ€# “€+ €c ?€ L€Ç ¯&É Å&Û Ô&Ü ß&Ý ë€ ÷   € € )€ 5€ B€ N€ Z€ g€ u€ € € € ¬€ ¹€ Æ€ Ò€ á€! ï€" ü€# €'€)(€*6€+E€,S€-b€0p€1€GŒ€H™€I§€Kµ€LÀù€†K€Žm€{€§-€Ìg€"Š€#²€$ڀ Ç\€ 7$HA„DHDHDIDJÀàG€ô$á  áDDáDáDTDVD\$D]8D_DD`XDbhDc|DeŒDg Di¼DlÈDnØDqàDvìDxðDyøD| D} D~,D€TD\DƒhD…¼D†ØD‡äD‰DŠHDŒLD„D D’¬D“´D”¼D—ØDDžD¡D¢D£$D¤,D§4DS€DT¤DV¬DWDY$DZ”D\œD] D_D``DbˆDc”DeœDf DhDi„DkŒDlØDnDo DqDr`DtˆDu”DwœDxèDz D{ D} $D~ pD€ ˜D ¤Dƒ ¬D„ øD† D‡ ,D‰ 4DŠ €DŒ ¨D ´D ¼D D’ 0D“ <D• DD– D˜ ¸D™ ÄD› ÌDœ Dž @DŸ LD¡ TD¢  D¤ ÈD¥ ÔD§ ÜD¨ (Dª PD« \D­ dD® °D° ØD± äD³ ìD´8D¶`D·lD¹tDºÀD¼èD½ôD¿üDÀHDÂpDÃ|DÅ„DÆÐDÈøDÉDË DÌXD΀DÏŒDÑ”DÒDÔ DÕXD×€DØŒDÚ”DÛàDÝDÞDàDáhDãDäœDæ¤DçðDéDê$Dì,DíœDï¤DððDòDó$Dõ,DöxDø Dù¬Dû´DüDþ(Dÿ4D<DˆD°D¼DÄDD 8D DD LD˜DÀDÌDÔD DHDTD\D¨DÐDÜDäD 0D"XD#dD%lD&¸D(àD)ìD+ôD,@D.hD/tD1|D2ÈD4ðD5üD7D8PD:xD;„D=ŒD>ØD@DA DCDD`DFˆDG”DIœDJèDLDMDO$DPpDR˜DS¤DU¬DVøDX DY,D[4Db€DdðDeüDgDnPDpÀDqÌDsÔDz D| D}¬D´D† Dˆ pD‰ |D‹ „DŒ ÐDŽ ØD!HD‘!PD”!\D–!\D™!pDœ!|D§!”D¨!¨D©!¼D³!ÌD´!øD·!øD¹"DÄ"DÆ",DÈ"4DË"DDÌ"dDÍ"hDÒ"xDÓ"€D×"DÛ"ØDÝ"àDè"ôDê#Dë#$Dð#4Dñ#HDó#XDø#`Dú#xDü#„Dý#ŒDþ#”D#œD#¼D#ÈD#ÐD#ØD #àD#èD$@â1@ã;@ãE@äÀÀÈO@}À àLÀÀX€–ÿÿÿìÀ!\À!Ìt€µÿÿÿèÀ!øà"ˆà#àà#èà#øà#øà#øà$„$DDDD D$D&HD(XD*pD/D7¤D>°D@ÈDAàDCüDGDJ0DK0DNHDV`DXlD[„D\˜D]˜D_¬D`¼DbäDgüDk(Dm0DoDDqTDtlDxŒDy D|¨D}ÈDD‚(D„<D†HD‡PDŒhDŽpD“ˆD•ŒD– D—¼D™ØD›ìDœøž@§@ ²@!Ä@!É€"ÿÿÿìÀÀüÓ€KÿÿÿèÀ0á€Vÿÿÿ俀XÿÿÿàÀHÀ„ú€]ÿÿÿÜÀ˜à à0à„à(à(àø$¢D¢D¢D¦D§ D©D«@D¬„D®¬D¯´D±ÀD³D´0Dµ<D·`D¸ Dº¬D»¸"@£6@¤ ÀÀ@@« À$à à¬à¸I$Êa ÊDDÊDÊDÌDÎDÏDÑ@DÒLDÔXDÖ´DרDØèDÚ DÛTDÝdDÞŒu@Ë‚@Ì Œ@Î ÀàŒ•$é§ éD¬@éDéDé Dê DíDï Dð<Dò<DóHDõhDøxDù˜Dû¸DüÀDþÈDèDDD$D,D 8D @¶@êÀ À À@òÒ@óÛ@õÀ<ààà@æ$DDDDD8D8D dD#xD$xD%D'¬D5ôD;D<D>$D?8DAHDH\DItDN|DODPœDRÈDTäDUðõ€ÿÿÿìÀÀÀ8À8ù€$ÿÿÿèÀxà|à|à|à|àð$^ ^DD^D^D_D`Db8DcLDdTÀàT($mU mDDmDmDnDo Dq(Dt<DuPDvdDyxDz„DŒD‚˜Àà˜d$ŠDŠDŠD‹DŒD4DŽHD\Àà\$™  ™D© ™HD™D™ Dœ DDž,D <D¥HD¦hD§|D©ŒD«˜D­¨D®´±€šÿÿÿìÀ à´¶$·à ·DD·D·D¸D¹D» D¼8D¾@D¿TDÁdDÂpÀàpæ$Ô ÔD ÔHDÔDÔ DÕ D×DØ$Dà0Dã€À à€#$íL íDDíDíDîDïDñ D÷(Dø4DúHDüXDýdDÿlD„DŒÀàŒR$ l  Du  HD D D DlDxDˆD˜D¨D¸DÌDÔDÜDìDôD D!D#D%D&(}€ ÿÿÿìÀ à(‚$1› 1DD1D1D3D48D6PD7lª€2ÿÿÿìÀàl°$CÉ CDÔ CHDCDC DJ DKDL(DM8DOHDPhDR DTÀDUÔDVäD[ôD]D^ Û€Dÿÿÿìà€Eÿÿÿèç€Fÿÿÿäë€GÿÿÿàÀ à ï$   DD D D¡D¢$D£0Àà0$à( àDDàDàDáDâ Àà 0$ëK ëDS ëHDëDë Dó Dô(À à([$üq üDDüDüDýDþÀày€G$’_@’i ’HD’D’ D“(D”(D•@À(à4v$—“@— —HD—D— D˜ D™$À à$©$›¸@› ›HD›D›DœD4Àà$Ï à& ð$ þ@ @ „D D D <Àà>$ U@ D D D $Àà_ Øi(Óy(Õ‡(⦠±±&Ì&/ã&Oû&Y&i &y8&D(§_(¨z(‹dgcl.lex.cgcc2_compiled./a/local/isasun29/1/mitarb/felix/pretzel/contrib/aj/gcl.lex.cint:t1=r1;-2147483648;2147483647;char:t2=r2;0;127;long int:t3=r1;-2147483648;2147483647;unsigned int:t4=r1;0;-1;long unsigned int:t5=r1;0;-1;long long int:t6=r1;01000000000000000000000;0777777777777777777777;long long unsigned int:t7=r1;0000000000000;01777777777777777777777;short int:t8=r1;-32768;32767;short unsigned int:t9=r1;0;65535;signed char:t10=r1;-128;127;unsigned char:t11=r1;0;255;float:t12=r1;4;0;double:t13=r1;8;0;long double:t14=r1;16;0;bool:t15=@s32;-16;void:t16=16__wchar_t:t17=r1;-2147483648;2147483647;__vtbl_ptr_type:T18=s8__delta:8,0,16;__index:8,16,16;__pfn:19=*16,32,32;__delta2:8,32,16;;__vtbl_ptr_type:t18size_t:t4fpos_t:t3FILE:t20=s16_cnt:1,0,32;_ptr:21=*11,32,32;_base:21,64,32;_flag:11,96,8;_file:11,104,8;._0::22=##23=*20;:__3._0;2A.24=##23;:__3._0RC3._0;2A.;__as::25=##26=&20;:3._0RC3._0;2A.;;div_t:t27=s8quot:1,0,32;rem:1,32,32;._1::28=##29=*27;:__3._1;2A.30=##29;:__3._1RC3._1;2A.;__as::31=##32=&27;:3._1RC3._1;2A.;;ldiv_t:t33=s8quot:3,0,32;rem:3,32,32;._2::34=##35=*33;:__3._2;2A.36=##35;:__3._2RC3._2;2A.;__as::37=##38=&33;:3._2RC3._2;2A.;;lldiv_t:t39=s16quot:6,0,64;rem:6,64,64;._3::40=##41=*39;:__3._3;2A.42=##41;:__3._3RC3._3;2A.;__as::43=##44=&39;:3._3RC3._3;2A.;;uid_t:t3wchar_t:t17physadr_t:t45=*46=xs_physadr_t:label_t:t47=xs_label_t:lock_t:t11uchar_t:t11ushort_t:t9uint_t:t4ulong_t:t5caddr_t:t48=*2daddr_t:t3off_t:t3cnt_t:t8paddr_t:t5use_t:t11sysid_t:t8index_t:t8boolean_t:t49=eB_TRUE:1,B_FALSE:0,;longlong_t:t6u_longlong_t:t7offset_t:t6diskaddr_t:t6lloff_t:t50=u8_f:6,0,64;_p:51=s8_u:3,0,32;_l:3,32,32;._6::52=##53=*51;:__Q23._53._6;2A.54=##53;:__Q23._53._6RCQ23._53._6;2A.;__as::55=##56=&51;:Q23._53._6RCQ23._53._6;2A.;;,0,64;._5::57=##58=*50;:__3._5;2A.59=##58;:__3._5RC3._5;2A.;__as::60=##61=&50;:3._5RC3._5;2A.;;lldaddr_t:t62=u8_f:6,0,64;_p:63=s8_u:3,0,32;_l:3,32,32;._8::64=##65=*63;:__Q23._73._8;2A.66=##65;:__Q23._73._8RCQ23._73._8;2A.;__as::67=##68=&63;:Q23._73._8RCQ23._73._8;2A.;;,0,64;._7::69=##70=*62;:__3._7;2A.71=##70;:__3._7RC3._7;2A.;__as::72=##73=&62;:3._7RC3._7;2A.;;k_fltset_t:t5id_t:t3major_t:t5minor_t:t5pri_t:t8o_mode_t:t9o_dev_t:t8o_uid_t:t9o_gid_t:t9o_nlink_t:t8o_pid_t:t8o_ino_t:t9key_t:t1mode_t:t5gid_t:t3nlink_t:t5dev_t:t5ino_t:t5pid_t:t3ssize_t:t1time_t:t3clock_t:t3clockid_t:t1timer_t:t1unchar:t11ushort:t9uint:t4ulong:t5hostid_t:t3u_char:t11u_short:t9u_int:t4u_long:t5quad:t74=xs_quad:timespec_t:t75=xstimespec:timestruc_t:t75itimerspec_t:t76=xsitimerspec:hrtime_t:t6siginfo_t:t77=xssiginfo:k_siginfo_t:t78=xsk_siginfo:sigqueue_t:t79=xssigqueue:fd_mask:t3fd_set:Tt80=s128fds_bits:81=ar1;0;31;3,0,1024;fd_set::82=##83=*80;:;2A.84=##83;:RC6fd_set;2A.;__as::85=##86=&80;:RC6fd_set;2A.;;YY_BUFFER_STATE:t87=*88=xsyy_buffer_state:yy_size_t:t4yy_buffer_state:Tt88=s40yy_input_file:23,0,32;yy_ch_buf:48,32,32;yy_buf_pos:48,64,32;yy_buf_size:4,96,32;yy_n_chars:1,128,32;yy_is_our_buffer:1,160,32;yy_is_interactive:1,192,32;yy_at_bol:1,224,32;yy_fill_buffer:1,256,32;yy_buffer_status:1,288,32;yy_buffer_state::89=##87;:;2A.90=##87;:RC15yy_buffer_state;2A.;__as::91=##92=&88;:RC15yy_buffer_state;2A.;;yy_current_buffer:S87yy_c_buf_p:S48yy_init:S1yy_start:S1YY_CHAR:t11yyin:G23yyout:G23yy_state_type:t1_G_clock_t:t3_G_dev_t:t5_G_fpos_t:t3_G_gid_t:t3_G_ino_t:t5_G_mode_t:t5_G_nlink_t:t5_G_off_t:t3_G_pid_t:t3_G_ptrdiff_t:t1_G_sigset_t:t1_G_size_t:t4_G_time_t:t3_G_uid_t:t3_G_wchar_t:t17_G_ssize_t:t1_G_wint_t:t3_G_va_list:t19_G_int8_t:t10_G_uint8_t:t11_G_int16_t:t8_G_uint16_t:t9_G_int32_t:t3_G_uint32_t:t5_G_int64_t:t6_G_uint64_t:t7streamoff:t3streampos:t3streamsize:t1__fmtflags:t5__iostate:t11io_state:t93=ebadbit:4,failbit:2,eofbit:1,goodbit:0,;open_mode:t94=ebin:128,noreplace:64,nocreate:32,trunc:16,app:8,ate:4,out:2,in:1,;seek_dir:t95=eend:2,cur:1,beg:0,;_seek_dir:t95_IO_marker:Tt96=s12_next:97=*96,0,32;_sbuf:98=*99=xs_IO_FILE:,32,32;_pos:1,64,32;_IO_marker::100=##97;:;2A.101=##97;:RC10_IO_marker;2A.;__as::102=##103=&96;:RC10_IO_marker;2A.;;_IO_FILE:Tt99=s76_flags:1,0,32;_IO_read_ptr:48,32,32;_IO_read_end:48,64,32;_IO_read_base:48,96,32;_IO_write_base:48,128,32;_IO_write_ptr:48,160,32;_IO_write_end:48,192,32;_IO_buf_base:48,224,32;_IO_buf_end:48,256,32;_IO_save_base:48,288,32;_IO_backup_base:48,320,32;_IO_save_end:48,352,32;_markers:97,384,32;_chain:98,416,32;_jumps:104=*105=xs_IO_jump_t:,448,32;_fileno:1,480,32;_blksize:1,512,32;_offset:3,544,32;_cur_column:9,576,16;_unused:2,592,8;_shortbuf:106=ar1;0;0;2,600,8;_IO_FILE::107=##98;:;2A.108=##98;:RC8_IO_FILE;2A.;__as::109=##110=&99;:RC8_IO_FILE;2A.;;__manip:t111=*112=f113=&114=xsios:__imanip:t115=*116=f117=&118=xsistream:__omanip:t119=*120=f121=&122=xsostream:Format_command:t123=ecancel:18,no_indent:17,big_force:16,force:15,break_space:14,backup:13,opt9:12,opt8:11,opt7:10,opt6:9,opt5:8,opt4:7,opt3:6,opt2:5,opt1:4,opt0:3,outdent:2,indent:1,null:0,;Latex_cweb_output:Tt124=s44!1,020,125=xsOutput:;Latex_cweb_output::126=#124,16,127=*124,1,16;:_._17Latex_cweb_output;2A*1;125;128=##127;:R7ostream;2A.;flush_output::129=##16;:;0A*2;125;;;~%125;Pscan:Tt130=s4.vf130:131=*132=ar1;0;1;18,0;Pscan::133=#130,16,134=*130,1,16;:_._5Pscan;2A.135=##134;:P7istream;2A.136=##134;:RC5Pscan;2A.;__as::137=##138=&130;:RC5Pscan;2A.;scan::139=##1;:PP9Attribute;2A*1;130;;;~%130;yywrap:F1gcl.lAttribute:Tt140=s4.vf140:131,0;Attribute::141=##142=*140;:;2A.143=##142;:RC9Attribute;2A.;__as::144=##145=&140;:RC9Attribute;2A.;print::146=##16;:R6Output;2A*1;140;;;~%140;yylex__FPP9Attribute:F1rvalue:p147=*142yy_current_state:r1yy_cp:r48yy_bp:r48yy_act:r1yy_c:r11yy_amount_of_matched_text:1yy_next_state:1yy_get_next_buffer__Fv:f1dest:r48source:r48number_to_move:r1i:r1ret_val:1num_to_read:1b:87yy_c_buf_p_offset:1new_size:1yy_get_previous_state__Fv:f1yy_current_state:r1yy_cp:r48yy_c:r11yy_try_NUL_trans__Fi:f1yy_current_state:p1yy_is_jam:r1yy_cp:r48yy_c:r11yyunput__FiPc:f16c:p1yy_bp:P48yy_cp:r48number_to_move:r1dest:r48source:r48yyinput__Fv:f1c:1offset:1yyrestart__FP4FILE:F16input_file:p23yy_switch_to_buffer__FP15yy_buffer_state:F16new_buffer:p87yy_load_buffer_state__Fv:F16yy_create_buffer__FP4FILEi:F87file:p23size:p1b:87yy_delete_buffer__FP15yy_buffer_state:F16b:p87yy_init_buffer__FP15yy_buffer_stateP4FILE:F16b:p87file:p23yy_flush_buffer__FP15yy_buffer_state:F16b:p87yy_scan_buffer__FPcUi:F87base:p48size:p4b:87yy_scan_string__FPCc:F87yy_str:p148=*2len:1yy_scan_bytes__FPCci:F87bytes:p148len:p1b:87buf:48n:4i:1yy_fatal_error__FPCc:f16msg:p148yy_flex_alloc__FUi:f19size:p4yy_flex_realloc__FPvUi:f19ptr:p19size:p4yy_flex_free__FPv:f16ptr:p19Ppscan:Tt149=s4!1,020,130;Ppscan::150=#149,16,151=*149,1,16;:_._6Ppscan;2A.152=##151;:P7istream;2A.153=##151;:RC6Ppscan;2A.;__as::154=##155=&149;:RC6Ppscan;2A.;scan::156=##1;:PP9Attribute;2A*1;130;;;~%130;__6PpscanP7istream:F151this:P151is:p157=*118scan__6PpscanPP9Attribute:F1this:P151rvalue:p147_._6Ppscan:F16this:P151__in_chrg:p1_vt.6Ppscan:G132_vt.5Pscan:S132_._5Pscan:F16this:P134__in_chrg:P1/users/felix/lib/pretzel/include/Pscan.h__5PscanP7istream:F134this:P134yyleng:G1yy_hold_char:S2yy_n_chars:S1yy_did_buffer_switch_on_eof:S1yytext:G48yy_accept:S158=ar1;0;106;8yy_ec:S159=ar1;0;255;1yy_meta:S160=ar1;0;51;1yy_base:S161=ar1;0;109;8yy_def:S161yy_nxt:S162=ar1;0;177;8yy_chk:S162yy_last_accepting_state:S1yy_last_accepting_cpos:S48yyin_stream:S157ÿñÿñ (0À%ÀÐ- Ü5=5d(P\,Ìøh5Œ0–$0­ ¶à ÛÀáýèÖ5,8)ð”1+„H? lÜF ¬dM HdTØ_q5¼ƒŽ™¡¦È².Ä\Å1à”êñ6Ì,"/  16H0$¼cry0àxŸ´5ØHÇ1Xˆñ6 ,  +3¤t@$U4j6ˆD"t{/Àd”›¢©±ÃÉÜí2t06L<gcl.lex.cyy_get_previous_state__Fvyy_metayy_baseyy_inityy_flex_alloc__FUiyyin_streamyyinput__Fvyy_flex_realloc__FPvUiyy_last_accepting_cposyy_get_next_buffer__Fvyy_startyy_hold_charyy_last_accepting_stateyy_ecyy_did_buffer_switch_on_eofyy_acceptyy_fatal_error__FPCcyy_try_NUL_trans__Fiyyunput__FiPcyy_defyy_chkyy_nxt_vt.5Pscanyy_current_bufferyy_flex_free__FPvyy_c_buf_pyy_n_chars_Q_qtodfree_vt.6Ppscanyyrestart__FP4FILEyy_flush_buffer__FP15yy_buffer_statemalloc__5PscanP7istreamexityy_switch_to_buffer__FP15yy_buffer_stateyyinread__7istreamPciyy_create_buffer__FP4FILEi__pure_virtualfilenoyy_delete_buffer__FP15yy_buffer_statejoin__FP9AttributeT0__6PpscanP7istreamyy_init_buffer__FP15yy_buffer_stateP4FILEscan__6PpscanPP9Attributeyyoutreallocisattyeof__C3iosyy_scan_string__FPCcyylex__FPP9Attributeyy_scan_bytes__FPCci_._5Pscanfwriteyy_load_buffer_state__Fvyylengyywrapyytextfprintftypeset_pred__FPc__iobjoin__FP9Attribute__builtin_deleteyy_scan_buffer__FPcUi_._6Ppscancreate__FPcgcount__7istream  $ 4 8 < @ P X \, `, p, tE xE |, €6 „6 ”6 ˜E œE  6 ¤ ¨ ¸, ¼, Ä.Ì Ð Ô?ð ô ø ü      4 À8 ÀL èP èl p t x ˆ Œ ¬ ¬° ¬Ü là l À  À( , L HP Hl p ¤ è¨ èÄ È Ì Ð Ü èà èðB ôB ø@ @      0 D4 DD (H LL ÄP <T ´X ,\ ´` ,d ¤h ,l ´p  <t  Äx  L|  Ô€  \„  äˆ  lŒ  ô  |” ˜ Œœ   œ¤ $¨ ¬¬ $° ¬´ 4¸ ¼¼ DÀ ¼Ä DÈ ÌÌ TÐ ÜÔ dØ ìÜ tà üä „è  ì ”ð ô ¤ø ,ü ´ < Ä L  ì Ì  œ  ð !t$ !h( , 4 8 < @ L@ P@ ` d h@ l@ pB tB ˜B œB  JÄ@ È@ Ø Ü à@ ä@ èB ìB B B J<@ @@ P T X@ \@ `B dB ˆB ŒB J´@ ¸@ È Ì Ð@ Ô@ ØB ÜB B B J,@ 0@ @ D H@ L@ PB TB x | €JF´@ ¸@ È Ì Ð@ Ô@ ØB ÜB B B J,@ 0@ @ D H@ L@ PB TB xB |B €J¤@ ¨@ ¸ ¼ À@ Ä@ ÈB ÌB ð ô øJF,@ 0@ @ D H@ L@ PB TB x | €JF´@ ¸@ È Ì Ð@ Ô@ ØB ÜB     J F <@ @@ P T X@ \@ `B dB ˆ 0 Œ 0 J  F Ä@ È@ Ø Ü à@ ä@ èB ìB  8  8 J (F L@ P@ ` d h@ l@ pB tB ˜ H œ H  J °F Ô@ Ø@ è ì ð@ ô@ øB üB  ` $ ` (J 8F \@ `@ p t x@ |@ €B „B ¨ x ¬ x °J ÀF ä@ è@ ø ü @ @ B B 0 ˆ 4 ˆ 8J HF l@ p@ € „ ˆ@ Œ@ B ”B ¸ ˜ ¼ ˜ ÀJ ÐF ô@ ø@   @ @ B B @ ° D ° HJ XF |@ €@  ” ˜@ œ@  B ¤B È È Ì È ÐJ àF@ @    @ $@ (B ,B P àT àXJhFŒ@ @   ¤ ¨@ ¬@ °B ´B Ø øÜ øàJðF@ @ ( , 0@ 4@ 8B <B ` d hJxFœ@  @ ° ´ ¸@ ¼@ ÀB ÄB è ì ðJF$@ (@ 8 < @@ D@ HB LB p t xJˆF¬@ °@ À Ä È@ Ì@ ÐB ÔB øB üB J$@ (@ 8 < @@ D@ HB LB p t xJˆF¬@ °@ À Ä È@ Ì@ ÐB ÔB ø ü JF4@ 8@ H L P@ T@ XB \B €  „  ˆJ˜F¼@ À@ Ð Ô Ø@ Ü@ àB äB  (  (J FD@ H@ X \ `@ d@ hB lB B ”B ˜J¼@ À@ Ð Ô Ø@ Ü@ àB äB  0  0J FD@ H@ X \ `@ d@ hB lB  @” @˜J¨FÌ@ Ð@ à ä è@ ì@ ðB ôB  @ @ J0FT@ X@ h l p@ t@ xB |B   X¤ X¨J¸FÜ@ à@ ð ô ø@ ü@ B B ( X, X0J@Fd@ h@ x | €@ „@ ˆB ŒB ° p´ p¸JÈFì@ ð@   @  @ B B 8 p< p@JPFt@ x@ ˆ Œ @ ”@ ˜B œB À xÄ xÈJØFü@ @   @ @  B $B H xL xPJ`F„@ ˆ@ ˜ œ  @ ¤@ ¨B ¬B Ð €Ô €ØJèF @ @   $ (@ ,@ 0B 4B X ˜\ ˜`JpF”@ ˜@ ¨ ¬ °@ ´@ ¸B ¼B à °ä °èJøF@  @ 0 4 8@ <@ @B DB h Èl ÈpJ€F¤@ ¨@ ¸ ¼ À@ Ä@ ÈB ÌB ð àô àøJF,@ 0@ @ D H@ L@ PB TB x ø| ø€JF´@ ¸@ È Ì Ð@ Ô@ ØB ÜB  ø øJF<@ @@ P T X@ \@ `B dB ˆ Œ J FÄ@ È@ Ø Ü à@ ä@ èB ìB   J(FL@ P@ ` d h@ l@ pB tB ˜ œ  J¬B °B ´JÄ2Ð (Ô (ØJè2øF@  @ 0 4 8@ <@ @B DB h 0l 0pJ|B €B „J”2  0¤ 0¨J¸2ÈFì@ ð@   @  @ B B 8 8< 8@JLB PB TDdJt2€ @„ @ˆJ˜2¨FÌ@ Ð@ à ä è@ ì@ ðB ôB  H  H J ,B 0B 4J D2 P H T H XJ h2 xF œ@  @ ° ´ ¸@ ¼@ ÀB ÄB ð@ ô@ ! ! ! @ !@ !B !B !<B !@@ !D6 !HB !L@ !T6 !X>!tB !xB !ˆ !Œ !” !˜ !¬" !° !´ !¼" !À !Ä !È, !Ì, !Ô !Ø !ä !è !ì !ð" !ø" " " "B "B "$ "DB "HB "\ "` "d "h "t " "” "ð "ô "øA#  #B #B # # #  #L #P #`, #d, #h&#x #|B #€B #Œ #œ #  #¤B #¨B #´ #¸ #¼ #À" #È" #Ð #à #ä #èB #ìB $ P$ P$4 $8 $@B $DB $H $L $P $T" $X" $h $x ˆ$| ˆ$ˆ $Œ $  $¤B $¨ $¬B $à $äB $è $ìB %, %0 %D %H %L" %P" %` %d % %” %œ %¤ &t À&x À&„ &˜ &œ &  &Ø &Ü &ä9&ø" &ü" ' '  ' ' '$-'," '0 '4 '8K'@" 'D 'H 'L" 'P" 'X" '\" '€, '„, 'ˆ&'  '¤ '¼" 'À" 'Ä" 'Ì" 'Ð 'Ô 'Ü" 'à" 'ì 'ð 'ô" 'ø" (B (  ( (B (4 (8 (< (@ (LB (PB (T (X (˜ À(œ À(¼ è(À è(Ü (à (ä (è (ø (ü ) ¬)  ¬)L l)P l)x À)| À)˜ )œ )¼ H)À H)ø )ü * è* è*0 *8 *< *@ *T *X *x ¬*| ¬*° l*´ l*ä À*è À+ +  +, H+0 H+ +” +˜ +œ +¤ +¨ +À" +Ä" +Ì +Ð +Ô +Ø +ì +ð +ü , ,L ,P ,T" ,X ,\ ,d" ,l ,p ,ˆ ð,Œ ð,¨B ,¬B ,° ,¸ ,¼ ,À ,Ð ,Ô ,Ø ,Ü ,ä ,è - - -  -" -" -  -0 -4 -D -HB -L -PB -\ -` -d -h -t -À, -Ä, -È&-ÐA-ð -ô ., ., . &.( .,B .0B .< .H .L .\ .` .h .l .p .t .x .„ . .” .˜ .Ì .Ð .à, .ä, .ì..ô .ø .ü / /4/?/( /, /H /L /\ /` /d /h /p /t /x /| /„ /ˆ /Œ" /" /˜ /  /¤?/¬ /´ /Ä" /È /Ì /Ô" /ØB /Ü /à /ä /ì /ðB /ô, /ø /ü 0, 0 0  0 0 0P 0T 0  0¤ 0Ä41 1 1 1 1h'1 01°82L 2T 2d?3  @3 @3ˆ+3ü<4P p4T p4àH4ü  5  54E 58E 5< À5@ À5HC5T*5p(5 75È$5ì)5ô% 5ø% 6 6 60;6X% 6\% 6h&6x=6” Ø6˜ Ø6´G6Ø Ø6Ü ØÔ5ä/ , ¬¸ÄÐ A |;à $0@ (0„ )ðŒ +„$ ,Ìì&p+ 0? ¨.!Œ1"44"Ä'#H$¼:%@<&` 5,&Ì 5d', 5Œ'˜ 5¼(3(|5(èI)`Ø)l=) 6ˆ)Ø)*8*D"*P*hè*tÀ*€À*Œ *˜ l*¤ H*° ¬*¼*È *Ô*à 6øas: SC4.0 dev 15 Feb 1995 GCC: (GNU) 2.7.24o ¤6ø7œ 7ÀEÐ$EÐ*ä *p´Œ3Ž@À #;“+C—,7¼ NÎè [ÏL fÑL-pretzel-2.0n-2/contrib/plugge/0000755000000000000000000000000006520317266015005 5ustar rootrootpretzel-2.0n-2/contrib/plugge/lx2l.l0000644000000000000000000001557406520317266016057 0ustar rootroot/*\c * \secb{Declarations for lx2l} * Copyright (C) 1995 -- 1998 Michael Plugge (m.plugge@fh-mannheim.de) * * This file is part of the cvt2ltx package, a package of LaTeX * converters. The whole package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License. See the files * config.h and COPYING for further details. * * Features included from (complete) lx2l: * macros: NO * conditionals: NO * threads: YES * character remapping: NO * include files: NO * xinclude files: NO * configuration files: NO * date and time: NO * native VMS CLI: NO * CVT2LTX specials: NO * warning if obsolete: NO * make full/make short: NO * lxx mode: NO * debug support: NO */ %{ #define LX_VERSION "1.0.0" #define BUFSIZE 32768 /* main buffer size */ #if VMS # include #endif #include #include #include #if VMS # undef ECHO # define ECHO (yyleng==1) ? fputc(*yytext,yyout) : fprintf(yyout,"%s",yytext) #endif #define NONE 0L #define ALL 0xffffffffL /* WARNING - if you want to increase THREAD_INDEX, RTFS first; you have to modify some rules * and also the following conditionals (UNDERLINE, LOCAL_COND*) are changed!!! */ #define THREAD_INDEX 10 /* maximum number of indices per thread character */ #define MAX_THREADS (THREAD_INDEX*26) /* don't change this value!! */ char *ptr,*ptr1,*mptr,*bu_ptr,*cptr,*buffer,thread_group[26+1],lx_only=1; int i,j,c,warn_def,ret_val,skip_start,init_sc,use_src,target_index,src_index,sc; long target_mode,src_mode[THREAD_INDEX],line=1; void print_time(char *format); char *copy_and_checkmode(char *optr); int die(char *cmd,int mode); %} WS [ \t\n] WSO [ \t\n]* SP [ \t]+ SPO [ \t]* THREAD (\{!?@@\^?[a-z0-9@()-]*\})|(\{@@@\^[a-z0-9()-]+\}) CONDITION_NAME [A-Z][A-Z0-9$_]* %x NEGATIVE_CLASS POSITIVE_CLASS SET_ALL_POSITIVE SET_ALL_NEGATIVE %option 8bit noyywrap never-interactive outfile="lx2l.c" %% for(i=0;i{ \([a-z]+\)[0-9-]+ { /* handle {@@a(bcd)345de} */ for(ptr=yytext+1,i=0;*ptr!=')';)thread_group[i++]= *ptr++-'a'; thread_group[i]=0; for(ptr++;*ptr;ptr++){ if(*ptr && *(ptr+1)=='-'){ for(i= *ptr-'0';i<= *(ptr+2)-'0';i++) for(ptr1=thread_group;*ptr1;)src_mode[i]|=(1L<<*ptr1++); ptr+=2; } else for(ptr1=thread_group;*ptr1;)src_mode[*ptr-'0']|=(1L<<*ptr1++); } } [a-z][0-9-]* { c=1L<<(*yytext-'a'); if(yyleng==1) src_mode[0]|=c; else{ for(ptr=yytext+1;*ptr;ptr++) if(*(ptr+1)=='-'){ for(i= *ptr-'0';i<= *(ptr+2)-'0';i++)src_mode[i]|=c; ptr+=2; } else src_mode[*ptr-'0']|=c; } } @ BEGIN(SET_ALL_POSITIVE); } { \([a-z]+\)[0-9-]+ { /* handle {@@^a(bcd)345de} */ for(ptr=yytext+1,i=0;*ptr!=')';)thread_group[i++]= *ptr++-'a'; thread_group[i]=0; for(ptr++;*ptr;ptr++){ if(*(ptr+1)=='-'){ for(i= *ptr-'0';i<= *(ptr+2)-'0';i++) for(ptr1=thread_group;*ptr1;)src_mode[i]&=~(1L<<*ptr1++); ptr+=2; } else for(ptr1=thread_group;*ptr1;)src_mode[*ptr-'0']&=~(1L<<*ptr1++); } } [a-z][0-9-]* { c=~(1L<<(*yytext-'a')); if(yyleng==1) src_mode[0]&=c; else{ for(ptr=yytext+1;*ptr;ptr++) if(*(ptr+1)=='-'){ for(i= *ptr-'0';i<= *(ptr+2)-'0';i++)src_mode[i]&=c; ptr+=2; } else src_mode[*ptr-'0']&=c; } } @ BEGIN(SET_ALL_NEGATIVE); } { [0-9]\-[0-9] for(i= *yytext-'0';i<= *(yytext+2)-'0';i++)src_mode[i]=ALL; [0-9] src_mode[*yytext-'0']=ALL; [a-z] c=1L<<(*yytext-'a'); for(i=0;i{ [0-9]\-[0-9] for(i= *yytext-'0';i<= *(yytext+2)-'0';i++)src_mode[i]=NONE; [0-9] src_mode[*yytext-'0']=NONE; [a-z] c=~(1L<<(*yytext-'a')); for(i=0;i[^a-z0-9}] | [^a-z0-9@}] { fprintf(stderr,"error: bad thread syntax %s in line %ld; disable output\n", buffer,line); use_src=0; BEGIN(sc); } \} { if(src_mode[target_index]&target_mode || target_mode==ALL)use_src=1; BEGIN(sc); } ^{SPO}\n { if(use_src)fputc('\n',yyout); line++; lx_only=1; } \n { if(use_src && !lx_only)fputc('\n',yyout); line++; lx_only=1; } . { if(use_src){ lx_only=0; fputc(*yytext,yyout); } } %% int die(char *cmd,int mode) { switch(mode){ case 1: fprintf(stderr,"Can't open %s for read; exit\n",cmd); exit(4); case 2: fprintf(stderr,"Can't open %s for write; exit\n",cmd); exit(4); case 3: fprintf(stderr,"%s\n",cmd); exit(4); default: return 0; } } int main(int argc,char **argv) { #if VMS ret_val=1; #else ret_val=0; #endif if(argc<4){ fprintf(stderr,"missing arguments for lx2l\n\ usage: lx2l \n"); exit(4); } buffer=malloc(512); warn_def=1; bu_ptr=calloc(BUFSIZE,1); target_mode=ALL; target_mode=1L<<(*argv[1]-'a'); if(c= *(argv[1]+1)) target_index=c-'0'; else target_index=0; (yyin=fopen(argv[2],"r")) || die(argv[2],1); (yyout=fopen(argv[3],"w")) || die(argv[3],2); #ifdef FLEX_DEBUG if(yy_flex_debug){ fprintf(stderr,"redirect stderr to file lx2l.dbg\n"); freopen("lx2l.dbg","w",stderr); } #endif /* FLEX_DEBUG */ yylex(); fclose(yyin); fclose(yyout); return(ret_val); } pretzel-2.0n-2/contrib/noweb/0000755000000000000000000000000006367034374014641 5ustar rootrootpretzel-2.0n-2/contrib/noweb/cee.latex/0000755000000000000000000000000006367034375016512 5ustar rootrootpretzel-2.0n-2/contrib/noweb/cee.latex/cee.ft0000644000000000000000000001263406255316374017605 0ustar rootroot/* cee.ft - Felix Gaertner's first pretzel formatted token file for simple C * * target formatter: LaTeX * * $Id: cee.ft,v 1.1 1996/12/16 19:02:09 gaertner Exp $ * * History at end. */ ALPH [a-zA-Z] ALPHNUM [a-zA-Z0-9_] ALPHNUMDOT [a-zA-Z0-9\.] DECDIGIT [0-9] HEXDIGIT [0-9A-Fa-f] EXP ([eE][+-]?[0-9]+) %{ #include // forward declaration of a function that replaces `_' // with `\_' in a copy of s char* escaped_underlines(char* s); %} %% // unary or binary operators for math mode "+" | "-" UNORBINOP "*" UNORBINOP { "\\hbox{$\\ast$}" } "/" | "<" | "=" | ">" | "." | "|" BINOP "%" BINOP { "\\hbox{\\tt\\%}" } "?" QUESTION "!" UNOP "~" UNOP { "\\hbox{\\verb+~+}" } "&" UNORBINOP { "\\&" } "," COMMA { "\\mathout, "} "(" LPAR "[" LBRACK ")" RPAR "]" RBRACK "{" LBRACE { "\\{" } "}" RBRACE { "\\}" } ";" SEMI ":" COLON "++" | "--" UNOP { "\\mbox{\\tt" ** "}" } // binary operators for math mode "!=" BINOP { "\\neq" } "<=" BINOP { "\\leq" } ">=" BINOP { "\\geq" } "==" BINOP { "\\equiv" } "&&" BINOP { "\\land" } "||" BINOP { "\\lor" } "->" BINOP { "\\to" } ">>" BINOP { "\\gg" } "<<" BINOP { "\\ll" } "+=" BINOP { "\\hbox{{\\tt +}=}" } "-=" BINOP { "\\hbox{{\\tt -}=}" } "*=" BINOP { "\\hbox{{\\tt *}=}" } "/=" BINOP { "\\hbox{{\\tt /}=}" } // preprocessor directives: "#" INSERT { "\\#" } "#include" | "#ifdef" | "#ifndef" | "#undef" | "#elif" | "#error" | "#pragma" | "#endif" LPROC { "{\\bf \\" + ** + "}" } "this" | "NULL" NUMBER { "{\\tt " ** "}" } // reserved words: // types and alike: "auto" | "char" | "const" | "double" | "extern" | "FILE" | "float" | "int" | "long" | "register" | "short" | "static" | "unsigned" | "volatile" | "void" | "friend" | "inline" | "virtual" | "signed" INT_LIKE { "{\\bf " + ** + "}" } "enum" | "union" | "class" | "struct" STRUCT_LIKE { "{\\bf " + ** + "}" } "delete" | "new" | "operator" | "sizeof" SIZEOF_LIKE { "{\\bf " + ** + "}" } "define" DEFINE_LIKE { "{\\bf " + ** + "}" } // case statement handling: "break" | "case" | "continue" | "default" | "private" | "protected" | "public" | "template" | "return" CASE_LIKE { "{\\bf " + ** + "}" } "switch" IF_LIKE { "{\\bf " + ** + "}" } // control structures: "do" DO_LIKE { "{\\bf " + ** + "}" } "else" ELSE_LIKE { "{\\bf " + ** + "}" } "for" | "if" | "while" IF_LIKE { "{\\bf " + ** + "}" } // type constructors "typedef" TYPEDEF_LIKE { "{\\bf " + ** + "}" } // comments: "/*"[^\*]*"*/" INSERT // what's this? "<"{ALPHNUMDOT}+">" LPROC { "\n@literal \\verb|" ** "|\n" } // chunks and other stuff for noweb: ^"@use\ ".* CHUNK { "\n" + ** + "\n" } ^"@".* IGNORE { "\n" + ** + "\n" } // identifiers and constants: [1-9]{DECDIGIT}*[uU]?[lL]? NUMBER 0{DECDIGIT}*[uU]?[lL]? NUMBER // octal 0[xX]{HEXDIGIT}+[uU]?[lL]? NUMBER // hex {DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]? | "."{DECDIGIT}*{EXP}?[fdFD]? | {DECDIGIT}+{EXP}?[fdFD]? | {EXP}[fdFD]? NUMBER // font is added in formatted grammar {ALPH}{ALPHNUM}* ID { [create(escaped_underlines(yytext))] } // strings (relies upon that ^^K is active character in TeX) '([^']|\\')*' | \"([^\"]|\\\")*\" STRING { "\\verb*\013" ** "\013" } [\ \t\n] // gobble up whitespace . // forget all non-standard characters // somehow some strange characters are // sent to pretzel (TODO). forget them. %% // escaped_underines replaces every occurrence of `_' by // the two characters `\_' in a copy of the string pointed to // by s // // the implementation first counts the number of underlines in // the string s and allocates new memory for the string. It then // copies the string byte after byte into the new place and // takes care to insert a `\' before any underline. // // this is a bit dirty as we don't have a chance to free the // allocated space later on, but it's still better than messing // around with yytext. To minimize the amount of memory I have // added a test whether copying is needed or not. char* escaped_underlines(char* s) { char* tmp = s; int number_of_ul = 0; int left = 0; // s[left] is the next char to copy int right = 0; // place s[left] in tmp[right] // fprintf(stderr, "call of escaped_underlines\n"); // count underlines in s while (*tmp != 0) { if (*tmp == '_') number_of_ul++; tmp++; } // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul); if (number_of_ul == 0) { tmp = s; // skip copying } else { tmp = new char[strlen(s) + number_of_ul + 1]; assert(tmp!=NULL); // now start to copy while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but // some compilers choke on it if (s[left] == '_') { tmp[right] = '\\'; right++; } tmp[right] = s[left]; left++; right++; } tmp[right] = s[left]; /* terminate string */ } // fprintf(stderr, "escaped_underlines: in: %s, out: %s\n", s, tmp); return(tmp); } /* * $Log: cee.ft,v $ * Revision 1.1 1996/12/16 19:02:09 gaertner * Initial revision * * Revision 1.1 1996/03/28 11:28:32 gaertner * Initial revision * * Revision 1.2 1996/03/26 14:36:11 gaertner * Getting really ugly now. Maybe I should start with an existing grammar. * * Revision 1.1 1996/03/22 11:25:26 gaertner * Initial revision * */ pretzel-2.0n-2/contrib/noweb/cee.latex/ceetest.nw0000644000000000000000000001111006255316375020505 0ustar rootroot% \documentclass{article} \usepackage{noweb,pretzel-noweb,a4} \begin{document} This is a small file ment to test the {\tt noweb} prettyprinting filter for C. @ Fist some simple noweb stuff. <<*>>= <> @ An empty chunk. <>= @ <>= <> <> @ Now let's start with some C stuff. <>= int an_int, another_int, and_still_another_int; char c, d; float a, b; float pi; double a, b, c, e, f, g; @ <>= short i1; short int i2; long i3; long int i4; long double doublette; unsigned int big_one; signed char odd_one; @ <>= int i = 1234; int a, b, i, g, l, o, n, g, r, o, w, o, f, in,t,e,g,e,r,s; long l = 123456789L; @ Let's try some octal and other esoteric stuff. <>= float f1 = 123.4, f2 = 1e-2, f3 = 1; int octal_int = 0777; @ The first line is an unsigned long with value 15. <>= int hex_int = 0x1f; float pi = 3.141, pi2; long hex_long = 0XFUL; char initialized_char = 'c', another_one = 'x', difficult_ones = '\n', another_difficult_one = '\777', bell = '\007'; @ <>= const float e = 2.71828182845905; const char msg[] = "warning: "; @ Now for some pointers and arrays. <>= int* ip; int int_array[]; int int_array[1000]; char* a_string; char** an_array_of_strings; char* s = "a string!"; int**** hey; int ****hey_hoh; int* zero = NULL; @ <>= int int_array[] = { 1, 2, 3, 4, 5, 6, 7, 0 }; @ Now for some operators. <>= x+x; x-x; x*x; x/x; x%x; x=y; x>y; x==y; x!=y; x&y; x&&y; x|y; x||y; ~x; ++x; x++; --x; x--; x+=2; x-=2; x*=2; x/=2; @ <>= a ? b : c; z = a ? 1 : 0; x= (n>1)? 1 : z; @ <>= p = &i; c = *a; cc = a->b; ccc = a.b; @ \section{Control Flow} <>= if (a==1) s=1; else s=2; if (a); @ <>= if (a != 0) { b=1; c=2; } if (n>0) if (a > b) z=a; else z=b; @ <>= if (a==b) s1(); else if (a!=b) s2(); else s3(); @ <>= switch (a) { case 1: s1(); break; case 2: s2(); break; default: s3(); } @ <>= for (i=0; isspace(s[i]); i++) ; for (i=0; i<100; i++) { a=i; } for (;;) { do_forever = 1; } while (c < 100) c++; while (c<1000) { c++; } do { i++; } while (i<100); for (i=0; i>= for (i=1; i<10; i++) { if (disaster) goto error; } error: i=42; @ page 70; \section{Constructed Types} Types defined by [[typedef]] should be handled like normal types and be typeset just like them. <>= typedef int Length; typedef char* String; Length len; Length len, maxlen; @ Let's see if if works in another chunk too. <>= String a_string; Length first = 100; @ \section{Hard Stuff} <>= char* entire_pped_code = has_been_pped.str(); (pp->ppcb)(pp->user_data, STRING, " "); (pp->ppcb)(pp->user_data, LITERAL, "\\begin{ppcode}"); char* line = strtok(entire_pped_code, "\n"); do { if (strlen(line) == 0) { (pp->ppcb)(pp->user_data, NEWLINE, NULL); continue; } if (*line == '@') { (pp->ppcb)(pp->user_data, WHATSIT, line); } else { (pp->ppcb)(pp->user_data, LITERAL, line); (pp->ppcb)(pp->user_data, NEWLINE, NULL); } } while ( (line = strtok( NULL, "\n" )) != NULL ); (pp->ppcb)(pp->user_data, LITERAL, "\\end{ppcode}"); @ Finally, it's our responsibility to cleanup the output [[strstream]], because we've called the [[str()]] function on it. <>= delete entire_pped_code; @ Some more hard stuff (taken from {\tt t1.w}). <

>= mlp = NULL; /* init match list pointer */ mp = mlp; hp = rp->right; /* point |hp| to beginning of round list */ while (hp != NULL) { if (hp->type == matches) { if (mp == NULL) { /* take this node as hew head */ mp = new_node(); check_node(mp); mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ mlp = mp; } else { /* add this one to the back */ mp->left = new_node(); check_node(mp->left); mp = mp->left; mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ } } hp = hp->left; /* look at next item of the list */ } @ That's it. \end{document} pretzel-2.0n-2/contrib/noweb/cee.latex/cee.fg0000644000000000000000000001774506360505163017571 0ustar rootroot/* cee.fg - Felix Gaertner's first formatted grammar for C * target is LaTeX, built for use with noweb * * $Id: cee.fg,v 1.2 1996/12/16 19:02:09 gaertner Exp $ * * History at end. */ %token BINOP %token UNORBINOP %token QUESTION %token UNOP %token LPAR %token RPAR %token LBRACE %token RBRACE %token LBRACK %token RBRACK %token SEMI %token COLON %token LPROC %token ID %token NUMBER %token INT_LIKE %token CASE_LIKE %token IF_LIKE %token DO_LIKE %token ELSE_LIKE %token TYPEDEF_LIKE %token STRUCT_LIKE %token SIZEOF_LIKE %token DEFINE_LIKE %token COMMA %token INSERT %token STRING %token CHUNK %token IGNORE %{ #include #include #include /* these functions help to typeset typedefs. they implement * a simple lookup table to see if an identifier is a * typedef or what... * * taken from Kernighan/Ritchie: The C Programming Language, p.144ff */ struct nlist { /* a table entry: */ struct nlist *next; /* next entry in chain */ char* name; /* the identifier */ }; #define HASHSIZE 101 static struct nlist* hashtab[HASHSIZE]; /* the hash table */ /* form the hash value of a string */ static unsigned hash(char* s) { // cerr << "hash(" << s << ") called." << endl; unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = *s + 31 * hashval; return hashval % HASHSIZE; } /* lookup: look for s in hashtab * * returns a pointer to the found element or NULL if it was not * found. */ static struct nlist* lookup(char* s) { // cerr << "lookup(" << s << ") called." << endl; struct nlist* np; for (np = hashtab[hash(s)]; np != NULL; np = np->next) if (strcmp(s, np->name) == 0) return np; /* found */ return NULL; /* not found */ } /* install: put name in hashtab. * * returns a pointer to the new element if all went well, * returns NULL on error. */ static struct nlist *install(char* name) { // cerr << "install(" << name << ") called." << endl; struct nlist* np; unsigned hashval; if ((np = lookup(name)) == NULL) { /* not found */ np = (struct nlist*) malloc(sizeof(*np)); if (np == NULL || (np->name = strdup(name)) == NULL) return NULL; hashval = hash(name); np->next = hashtab[hashval]; hashtab[hashval] = np; } return np; } /* attibute_to_string - * turn an attribute into a string * * idea: call print() with a strstream * * NB: Output has to be deleted and the strstream properly * terminated before calling .str()! Otherwise, the last * characters are garbeled. */ static char* attribute_to_string( Attribute* a ) { ostrstream printstream; Latex_cweb_output* o = new Latex_cweb_output(printstream); a->print(*o); delete o; printstream << ends; return printstream.str(); } /* forward declaration of debugging function */ static void debug_print( char* this_is, Attribute* stuff ); %} %% // inserting $s for TeX's math mode is quite tricky because // at the beginning of \LA and \RA noweb expects to not be in // math mode and complains about missing $s when we're already in // it. Solution: We'll use Lee's \mathin and \mathout macros to // surround expressions and alike. It's better to selectively invoke // math mode than have everything in it. final : exp { "\\mathin" $1 "\\mathout" } // [ debug_print("Final exp", $1); ] | stmt { $1 } // [ debug_print("Final stmt", $1); ] | error { "syntax error" } ; // get formatting of identifiers right id : ID { [ lookup(attribute_to_string($1)) ? create("{\\bf ") : create("{\\it ") ] $1 "}" } ; // ************************************************************ // format expressions: exp : NUMBER | STRING ; // easy things: // I don't know why I have duplicated everything (exp, id) but // I think it was in order for typedef to work correctly exp : exp UNOP // x++ | id UNOP | UNOP exp // ++x | UNOP id | exp BINOP exp | id BINOP exp | exp BINOP id | id BINOP id | exp UNORBINOP exp | id UNORBINOP exp | exp UNORBINOP id | id UNORBINOP id | UNORBINOP exp // *x | UNORBINOP id | LPAR exp RPAR // (x+1) | LPAR id RPAR | id LBRACK exp RBRACK // a[10] | id LBRACK id RBRACK // a[i] | id LBRACK RBRACK { $1 $2 "\\," $3 } // a[] | id LPAR decl_list RPAR { "\\hbox{" $1 $2 $3 $4 "}" } // f(x+1) f(a,b) | id LPAR RPAR { "\\hbox{" $1 $2 "\\," $3 "}" } // f() ; // ************************************************************** // declarations of variables with or without initializers decl : INT_LIKE decl_list { $1 "\\ " $2 } // int a, b, c | INT_LIKE INT_LIKE decl_list { $1 "\\ " $2 "\\ " $3 } // extern int a | id decl_list { $1 "\\ " $2 } // foo bar ; // lists like in function headings, i.e. f(int i, int b) params_list : decl | decl COMMA params_list { $1 $2 opt9 "\\ " $3 } ; // a sequence of variables (possibly with initializers) decl_like : exp { "\\mathin " $1 "\\mathout " } | id // i ; decl_list : decl_like | decl_like COMMA decl_list { $1 $2 opt9 $3 } ; stmt : decl SEMI // int i; ; // *************************************************************** // typedefs. it's important that the identifier is an ID token and // not an id token (which has italics around it already) typedef : TYPEDEF_LIKE INT_LIKE ID [ install(attribute_to_string($3)); ] { $1 "\\ " $2 "\\ {\\bf " $3 "}" } | TYPEDEF_LIKE INT_LIKE UNORBINOP ID // typedef char* String [ install(attribute_to_string($4)); ] { $1 "\\ " $2 $3 "\\ {\\bf " $4 "}" } ; stmt : typedef SEMI ; // *************************************************************** // statements stmt : exp SEMI { "\\mathin " $1 "\\mathout " $2 } ; // empty block stmt : LBRACE RBRACE { $1 "\\," $2 } | SEMI ; // block statement stmt : LBRACE stmt RBRACE { force $1 indent force $2 outdent force $3 force } ; // ***************************************************************** // control structures // if then / if then else / while / case stmt : IF_LIKE exp stmt { $1 "\\ \\mathin " $2 "\\mathout\\ " $3 } | IF_LIKE exp stmt ELSE_LIKE stmt { $1 "\\ \\mathin " $2 "\\mathout\\ " $3 "\\ " break_space $4 "\\ " $5 } ; // for loops stmt : IF_LIKE LPAR stmt stmt exp RPAR stmt // for (i=1;i<1;i++); { $1 "\\ \\mathin " $2 $3 "\\ " $4 "\\ " $5 $6 "\\mathout\\ " $7 } | IF_LIKE LPAR stmt stmt RPAR stmt // for (;;); { $1 "\\ \\mathin " $2 $3 "\\ " $4 $5 "\\mathout\\ " $6 } ; // do, case etc stmt : DO_LIKE stmt IF_LIKE exp SEMI { $1 $2 $3 "\\ \\mathin " $4 "\\mathout " $5 } | CASE_LIKE SEMI // return; | CASE_LIKE exp SEMI { $1 "\\ \\mathin " $2 "\\mathout " $3 } ; tag : CASE_LIKE COLON // default: | id COLON { "\n@def " $1 "\n" "\\mathin " $1 "\\mathout " $2 } | CASE_LIKE exp COLON { $1 "\\ \\mathin " $2 "\\mathout " $3 } | tag tag { $1 break_space $2 } // 1: 2: ; stmt : tag stmt { force backup $1 "\\ " opt9 $2 } // 1: a=1; ; // join up statements stmt : stmt stmt { $1 force $2 } | stmt SEMI // empty statemet ; // be sure not to be in math mode for chunks stmt : CHUNK SEMI { "\\mathout " $1 $2 force } | CHUNK ; exp : CHUNK { $1 } ; // *********************************************************** // preprocessor directives stmt : LPROC | LPROC stmt | LPROC STRING // #include "abc.h" | LPROC LPROC // #include | INSERT | IGNORE ; // ********************************************************* // do nothing rules for comments and ignores ... %% static void debug_print( char* this_is, Attribute* stuff ) { cerr << "*** " << this_is << ":" << endl; Latex_cweb_output os(cerr); stuff->print(os); } /* * $Log: cee.fg,v $ * Revision 1.2 1996/12/16 19:02:09 gaertner * release version * * Revision 1.1 1996/12/11 17:14:16 gaertner * Initial revision * */ pretzel-2.0n-2/contrib/noweb/cee.latex/index.list0000644000000000000000000000032406360721107020502 0ustar rootrootthis directory & a noweb prettyprinter for C and LaTeX (experimental) Makefile & the Makefile README & more information cee.fg & Pretzel formatted grammar cee.ft & Pretzel formatted tokens ceetest.nw & Test file pretzel-2.0n-2/contrib/noweb/cee.latex/README0000644000000000000000000000414506255316364017373 0ustar rootroot$Id: README,v 1.1 1996/12/16 19:02:09 gaertner Exp $ README for contrib/noweb/cee.latex A noweb prettyprinter for C using Pretzel Prerequisites: -------------- You need: - the Pretzel system (the new version 2.0x) - the noweb system Files: ------ Makefile README this file cee.ft formatted tokens for very simple C cee.fg formatted grammar for very simple C Using: ------ The files in contrib/noweb/general contain an explanation about the ideas involved here. All you need is a working version of pretzel-it. To use, change the cee.ft and cee.fg files to what you think will be a good prettyprinting style and then pretzel-it -n cee prettycee This will build an executable noweb filter that prettyprints the code parts according to the specs in cee.ft and cee.fg. make prettyceetest to run it on some example noweb files. There's a lot of debugging information around at the moment. Also, the LaTeX styles of Pretzel and noweb still bite eachother (working on this). You might want to look at the same stuff for HTML instead of LaTeX (in directory contrib/noweb/cee.html). Ommissions (work to be done): ----------------------------- o a lot Help (some is a little outdated): --------------------------------- o Why does pretzel-it not work? You have to set environment variables PRETZEL_LIBDIR and PRETZEL_INCLUDE to the correct paths of your Pretzel installation (e.g. something line /usr/local/lib/pretzel and /usr/local/include/pretzel). o Why does pretzel gobble up newlines when I prettyprint code? You probably have a line like [\t\ \n] // empty in your formatted token file. This naturally will gobble up all newlines sent to the prettyprinter by noweb. Pretzel by itself does not place any newlines into the prettyprinted output. You have to do this yourself, e.g. by stating \n NEWL in your formatted token file and then saying newl : NEWL ; in the formatted grammar, where the token newl is again reduced within a rule that is appropriate for parsing the newline token. pretzel-2.0n-2/contrib/noweb/cee.latex/index.html0000644000000000000000000000201106360721117020467 0ustar rootroot Index file for directory "pretzel/contrib/noweb/cee.latex" of Pretzel distribution

Index file for directory "pretzel/contrib/noweb/cee.latex" of Pretzel distribution

Files and directories are:

this directory

    a noweb prettyprinter for C and LaTeX (experimental)
Makefile
    the Makefile
README
    more information
cee.fg
    Pretzel formatted grammar
cee.ft
    Pretzel formatted tokens
ceetest.nw
    Test file

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 16:38:08 MESZ 1997 pretzel-2.0n-2/contrib/noweb/cee.latex/Makefile0000644000000000000000000000070006255316364020144 0ustar rootroot# $Id: Makefile,v 1.1 1996/12/16 19:02:09 gaertner Exp $ #---------------------------------------------------------------------- # # Makefile for C prettyprinting filter for noweb (using pretzel) # ceetest: prettycee noweave -delay -filter prettycee \ ceetest.nw > ceetest.tex prettycee: cee.ft cee.fg pretzel-it -nid cee prettycee dvi: ceetest latex ceetest.tex clean: rm -f *.tex *.log *.dvi *.o *.toc *.aux *.h *.c *.o *.l *.y pretzel-2.0n-2/contrib/noweb/cee.html/0000755000000000000000000000000010765024544016333 5ustar rootrootpretzel-2.0n-2/contrib/noweb/cee.html/index.list0000644000000000000000000000065506360656120020342 0ustar rootrootthis directory & experiments with Pretzel, noweb and HTML Makefile & The Makefile README & more Information cee2html.fg & simple formatted grammar for C cee2html.ft & simple formatted tokens for C cee2htmltest-sample.html & sample output of a noweb run cee2htmltest.nw & test file for the prettyprinter prettycee2html.nw & non-standard interface between Pretzel and noweb (replaces ../general/nowebpretzelpp.nw when linking) pretzel-2.0n-2/contrib/noweb/cee.html/README0000644000000000000000000000117706255316001017210 0ustar rootrootREADME for a noweb prettyprinter for HTML This is an experiment to use a different target from LaTeX. Here I use HTML. Files: Makefile README this file cee2html.fg simple formatted grammar for C cee2html.ft simple formatted tokens for C cee2htmltest.html output of a noweb run cee2htmltest.nw test file for the prettyprinter prettycee2html.nw non-standard interface between Pretzel and noweb (replaces ../general/nowebpretzelpp.nw when linking) To study how this all works, see the prettycee2html.nw file and study the differences to ../general/nowebpretzelpp.nw. Also, see the relevant sections of the Pretzelbook. pretzel-2.0n-2/contrib/noweb/cee.html/index.html0000644000000000000000000000277306360656131020340 0ustar rootroot Index file for directory "pretzel/contrib/noweb/cee.html" of Pretzel distribution

Index file for directory "pretzel/contrib/noweb/cee.html" of Pretzel distribution

Files and directories are:

this directory

    experiments with Pretzel, noweb and HTML
Makefile
    The Makefile
README
    more Information
cee2html.fg
    simple formatted grammar for C
cee2html.ft
    simple formatted tokens for C
cee2htmltest-sample.html
    sample output of a noweb run
cee2htmltest.nw
    test file for the prettyprinter
prettycee2html.nw
    non-standard interface between Pretzel and noweb
(replaces ../general/nowebpretzelpp.nw when linking)

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 11:39:38 MESZ 1997 pretzel-2.0n-2/contrib/noweb/cee.html/cee2htmltest.nw0000644000000000000000000001111106255315417021300 0ustar rootroot This is a small file ment to test the noweb prettyprinting filter for C and HTML. Doesn't look supergood, but should give you and idea of what's possible.

Fist some simple noweb stuff.

<<*>>= <> @ An empty chunk.

<>= @ <>= <> <> @ Now let's start with some C stuff.

<>= int an_int, another_int, and_still_another_int; char c, d; float a, b; float pi; double a, b, c, e, f, g; @ <>= short i1; short int i2; long i3; long int i4; long double doublette; unsigned int big_one; signed char odd_one; @ <>= int i = 1234; int a, b, i, g, l, o, n, g, r, o, w, o, f, in,t,e,g,e,r,s; long l = 123456789L; @ Let's try some octal and other esoteric stuff. <>= float f1 = 123.4, f2 = 1e-2, f3 = 1; int octal_int = 0777; @ The first line is an unsigned long with value 15. <>= int hex_int = 0x1f; float pi = 3.141, pi2; long hex_long = 0XFUL; char initialized_char = 'c', another_one = 'x', difficult_ones = '\n', another_difficult_one = '\777', bell = '\007'; @ <>= const float e = 2.71828182845905; const char msg[] = "warning: "; @ Now for some pointers and arrays. <>= int* ip; int int_array[]; int int_array[1000]; char* a_string; char** an_array_of_strings; char* s = "a string!"; int**** hey; int ****hey_hoh; int* zero = NULL; @ <>= int int_array[] = { 1, 2, 3, 4, 5, 6, 7, 0 }; @ Now for some operators. <>= x+x; x-x; x*x; x/x; x%x; x=y; x>y; x==y; x!=y; x&y; x&&y; x|y; x||y; ~x; ++x; x++; --x; x--; x+=2; x-=2; x*=2; x/=2; @ <>= a ? b : c; z = a ? 1 : 0; x= (n>1)? 1 : z; @ <>= p = &i; c = *a; cc = a->b; ccc = a.b; @

Control Flow

<>= if (a==1) s=1; else s=2; if (a); @ <>= if (a != 0) { b=1; c=2; } if (n>0) if (a > b) z=a; else z=b; @ <>= if (a==b) s1(); else if (a!=b) s2(); else s3(); @ <>= switch (a) { case 1: s1; break; case 2: s2; break; default: s3; } @ <>= for (i=0; isspace(s[i]); i++) ; for (i=0; i<100; i++) { a=i; } for (;;) { do_forever = 1; } while (c < 100) c++; while (c<1000) { c++; } do { i++; } while (i<100); for (i=0; i>= for (i=1; i<10; i++) { if (disaster) goto error; } error: i=42; @

Constructed Types

Types defined by [[typedef]] should be handled like normal types and be typeset just like them.

<>= typedef int Length; typedef char* String; Length len; Length len, maxlen; @ Let's see if if works in another chunk too.

<>= String a_string; Length first = 100; @

Hard Stuff

<>= char* entire_pped_code = has_been_pped.str(); (pp->ppcb)(pp->user_data, STRING, " "); (pp->ppcb)(pp->user_data, LITERAL, "\\begin{ppcode}"); char* line = strtok(entire_pped_code, "\n"); do { if (strlen(line) == 0) { (pp->ppcb)(pp->user_data, NEWLINE, NULL); continue; } if (*line == '@') { (pp->ppcb)(pp->user_data, WHATSIT, line); } else { (pp->ppcb)(pp->user_data, LITERAL, line); (pp->ppcb)(pp->user_data, NEWLINE, NULL); } } while ( (line = strtok( NULL, "\n" )) != NULL ); (pp->ppcb)(pp->user_data, LITERAL, "\\end{ppcode}"); @ Finally, it's our responsibility to cleanup the output [[strstream]], because we've called the [[str()]] function on it.

<>= delete entire_pped_code; @ Some more hard stuff (taken from t1.w).

<

>= mlp = NULL; /* init match list pointer */ mp = mlp; hp = rp->right; /* point |hp| to beginning of round list */ while (hp != NULL) { if (hp->type == matches) { if (mp == NULL) { /* take this node as hew head */ mp = new_node(); check_node(mp); mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ mlp = mp; } else { /* add this one to the back */ mp->left = new_node(); check_node(mp->left); mp = mp->left; mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ } } hp = hp->left; /* look at next item of the list */ } @ That's it.

pretzel-2.0n-2/contrib/noweb/cee.html/cee2html.fg0000644000000000000000000001035006255315416020353 0ustar rootroot/* cee2html.fg - pretzel formatted grammar file for simple C * * target formatter: HTML * * $Id: cee2html.fg,v 1.1 1996/12/16 18:53:15 gaertner Exp $ * * History at end. */ %token BINOP %token UNORBINOP %token QUESTION %token UNOP %token LPAR %token RPAR %token LBRACE %token RBRACE %token SEMI %token COLON %token LPROC %token ID %token NUMBER %token INT_LIKE %token CASE_LIKE %token IF_LIKE %token DO_LIKE %token ELSE_LIKE %token TYPEDEF_LIKE %token STRUCT_LIKE %token SIZEOF_LIKE %token DEFINE_LIKE %token COMMA %token INSERT %token STRING %token CHUNK %token IGNORE %% final : exp | stmt ; // get formatting of identifiers right id : ID ; exp : id { "" $1 "" } ; // ************************************************************ // format expressions: exp : NUMBER | STRING ; // easy things: exp : exp UNOP // x++ | UNOP exp // ++x | exp BINOP exp | exp UNORBINOP exp | UNORBINOP exp // *x | exp LPAR decl RPAR // f(int i) | exp LPAR exp RPAR // f(a+b) | exp LPAR RPAR // f() | LPAR exp RPAR ; exp : SIZEOF_LIKE exp INT_LIKE { $1 $2 " " $3 } // new(z) char ; exp : SIZEOF_LIKE exp { $1 " " $2 } | SIZEOF_LIKE LPAR decl RPAR // sizeof(struct s) | SIZEOF_LIKE INT_LIKE { $1 " " $2 } | SIZEOF_LIKE UNORBINOP { $1 " " $2 } | SIZEOF_LIKE BINOP { $1 " " $2 } | SIZEOF_LIKE UNOP { $1 " " $2 } | SIZEOF_LIKE SIZEOF_LIKE { $1 " " $2 } | SIZEOF_LIKE COMMA { $1 " " $2 } ; // ************************************************************** // declarations of variables with initializers decl : INT_LIKE exp { $1 " " $2 } // int a=1 | INT_LIKE INT_LIKE exp { $1 " " $2 " " $3 } // extern int a | exp exp { $1 " " $2 } // foo bar=1 | exp { $1 } // int foo=1, bar, foobar | decl COMMA INT_LIKE exp { $1 $2 force $3 $4 } | decl COMMA INT_LIKE exp decl { $1 $2 force $3 " " $4 " " $3 } | decl COMMA exp exp { $1 $2 force $3 " " $4 } | decl COMMA exp { $1 $2 force $3 } | STRUCT_LIKE exp LBRACE decl RBRACE exp // structs { $1 " " $2 " "$3 indent force $4 outdent force $5 " " $6 } | STRUCT_LIKE exp LBRACE stmt RBRACE exp { $1 " " $2 " " $3 indent force $4 outdent force $5 " " $6 } | STRUCT_LIKE exp LBRACE stmt RBRACE { $1 " " $2 " " $3 indent force $4 outdent force $5 } | STRUCT_LIKE decl { $1 " " $2 } ; stmt : decl SEMI // int i; ; stmt : decl stmt // ; // *************************************************************** // typedefs typedef : TYPEDEF_LIKE decl { $1 " " $2 } ; stmt : typedef SEMI ; // *************************************************************** // statements stmt : exp SEMI ; // empty statement stmt : LBRACE RBRACE ; // block statement stmt : LBRACE stmt RBRACE { force $1 indent force $2 outdent force $3 force } ; // ***************************************************************** // control structures // an `else_like' is something to which a statement may be appended // if then else else_like : IF_LIKE exp { $1 " " $2 } | ELSE_LIKE ; else_like : else_like stmt else_like { force $1 $2 force $3 " " cancel } // | else_like exp else_like ; // else-less if stmt : else_like stmt { $1 indent break_space $2 outdent force } ; // else if else_like : else_like else_like { $1 cancel " " $2 } ; // do, case etc stmt : DO_LIKE stmt else_like SEMI | CASE_LIKE SEMI // return; | CASE_LIKE exp SEMI { $1 " " $2 $3 } ; tag : CASE_LIKE COLON // default: | exp COLON { "\n@def " $1 "\n" $1 $2 } | CASE_LIKE exp COLON { $1 " " $2 $3 } | tag tag { $1 break_space $2 } ; stmt : tag stmt { force backup $1 opt9 $2 } ; // `for' constructs else_like : IF_LIKE LPAR stmt stmt exp RPAR | IF_LIKE LPAR SEMI stmt RPAR // for (; a;) | IF_LIKE LPAR stmt stmt RPAR // for (a; b;) ; // join up statements stmt : stmt stmt { $1 force $2 } | stmt SEMI // empty statemet ; stmt : CHUNK SEMI { $1 $2 force } | CHUNK ; exp : CHUNK ; // *********************************************************** // preprocessor directives stmt : LPROC | LPROC stmt | LPROC STRING // #include "abc.h" | LPROC LPROC // #include | INSERT | IGNORE ; %% /* * $Log: cee2html.fg,v $ * Revision 1.1 1996/12/16 18:53:15 gaertner * Initial revision * */ pretzel-2.0n-2/contrib/noweb/cee.html/Makefile0000644000000000000000000000167706255315416020006 0ustar rootroot# $Id: Makefile,v 1.1 1996/12/16 18:52:22 gaertner Exp $ #---------------------------------------------------------------------- # # Makefile for C prettyprinting filter for noweb (using pretzel) # with HTML as target # cee2htmltest: prettycee2html noweave -html -filter prettycee2html \ cee2htmltest.nw > cee2htmltest.html # use pretzel-it to build the C sources but link the code with # prettycee2html instead of the standard object (for LaTeX) prettycee2html: cee2html.ft cee2html.fg prettycee2html.o pretzel-it -i cee2html prettycee2html g++ cee2html.lex.o cee2html.tab.o prettycee2html.o \ ../../../nowebpretzelpp.o \ -I../../../include -L../../.. -lpretzel -g -o prettycee2html prettycee2html.o: prettycee2html.nw notangle prettycee2html.nw > prettycee2html.c g++ -c -I../../../include -I../general prettycee2html.c dvi: cee2htmltest latex cee2htmltest.tex clean: rm -f *.tex *.log *.dvi *.o *.toc *.aux *.h *.c *.o *.l *.y pretzel-2.0n-2/contrib/noweb/cee.html/prettycee2html.nw0000644000000000000000000003134210765024544021657 0ustar rootroot% noweb source % % $Id: prettycee2html.nw,v 1.1 1996/12/16 18:53:15 gaertner Exp $ % % History at end % \documentclass{article} \usepackage{noweb} \usepackage{pretzel-latex} \begin{document} \title{A Prettyprinter for {\tt noweb} that beautifies C to {\sc ASCII}\thanks{This file is nealy an exact copy of {\tt prettycee.nw}.}} \maketitle \tableofcontents \section{Introduction} This document describes the implementation of a prettyprinter for {\tt noweb} that outputs to an {\sc ASCII} terminal. There are two more files that contain a complete description of how the actual prettyprinter acts and what it outputs (the files {\tt cee2html.ft} and {\tt cee2html.fg}). By tuning these two file, you can make the output go to a line printer or look good when using {\tt HTML}. It is written in C++ and conforms to an API given to me by Norman Ramsey. This file is nealy an exact copy of {\tt prettycee.nw}. \section{Interface} [This section is the API by Norman Ramsey. Additional text by the current author is put in angled brackets.] Here is a suitable API for a prettyprinter for noweb. Input to be prettyprinted is a sequence of strings, newlines, and chunks used. A [[STRING]] is always free of newlines. <>= typedef enum parttype { START_OF_CHUNK=1, END_OF_CHUNK, STRING, USE_CHUNK, NEWLINE, LITERAL, DEFINITION, WHATSIT } Parttype; @ The prettyprinter calls back into the application as follows: <>= typedef void (*PrettyPrinterCallback) (void *closure, Parttype type, char *contents); @ The [[contents]] must be \begin{quote} \begin{tabular}{ll} [[START_OF_CHUNK]]&The name of the chunk being prettyprinted\\ [[END_OF_CHUNK]]&[[NULL]]\\ [[STRING]]&A string with no newlines\\ [[LITERAL]]${}^*$&A string with no newlines, to get no further formatting\\ [[USE_CHUNK]]&The name of the chunk referred to\\ [[NEWLINE]]&[[NULL]]\\ [[DEFINITION]]${}^*$&An identifier whose definition is in this chunk.\\ [[WHATSIT]]&An uninterpreted string passed to the callback function \end{tabular} \end{quote} Items marked with a star ($*$) are legal only when the prettyprinter is calling back into the application. The identifier given in [[DEFINITION]] isn't printed, so if the prettyprinter wants to print it, it has to send it twice. @ The prettyprinter exports two calls to the application. <>= typedef struct prettyprinter *PrettyPrinter; extern PrettyPrinter new_prettyprinter(PrettyPrinterCallback callback, void *closure); extern void prettyprint(PrettyPrinter pp, Parttype type, char *contents); @ The prettyprinter accepts calls to the [[prettyprint]] procedure. Any call to [[prettyprint]] may result in one or more callbacks to the procedure registered when [[new_prettyprinter]] is called. For any given [[PrettyPrinter]], the application must call [[prettyprint]] with [[type==END_OF_CHUNK]] exactly once, and that call must be the last call. <

>= <> @ \section{Implementation} \subsection{Overview} The implementation will use a prettyprinter generated by the Pretzel system. A Pretzel prettyprinter comes in the form of a class: % \begin{verbatim} // abstract base class of prettyprinter: #include #include"attr.h" #include"output.h" class Pparse { public: Pparse() {}; ~Pparse() {}; virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*) = 0; }; // actual prettyprinter: #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; \end{verbatim} % The idea of the implementation is to translate calls to the API functions into suitable sequences for the Pretzel prettyprinter. This is not the nicest way of doing it, but it seems the fastest solution at the moment. (A more elegant way would be to change Pretzel internals, but that is a different story.) I have analyzed the code of {\tt pretty.nw} and am using it as the filter which generates the calls to this prettyprinter. There will only be calls using the [[NEWLINE]], [[STRING]], [[USE_CHUNK]] and [[WHATSIT]] part types. The final call to [[prettyprint]] is with an [[END_OF_CHUNK]]. Here's an overview over the implementation. <<*>>= /* implementation of a noweb prettyprinter using Pretzel */ <
> <> <> @ Of course, we include our own header file, which is {\tt pretty.h} from the noweb distribution. <
>= #include "pretty.h" @ Because a Pretzel prettyprinter needs to see the entire text before it can start to prettyprint, we have to wait until an [[END_OF_CHUNK]] is sent, collecting all the strings and newlines coming in along the way. Having done this, we have a view of the entire code part, including chunk names, etc.~and can send all this to the Pretzel prettyprinting class (using C++ [[strstream]]s). Pretzel returns a long string again which is chopped up into lines and sent back to the application via the callback function. There are a few problems here: % \begin{itemize} \item Chunk uses have to be known to the prettyprinter in order to get the formatting (indentation etc.) right. This means that they have to be part of the prettyprinting grammar of pretzel. \item The [[WHATSIT]] parttypes would mess up the prettyprinter if they were sent to it because they will inevitably be seen by the parser and would mess up parsing! So we sent a [[WHATSIT]] directly back to the application if we see it. \end{itemize} \subsection{The Actual Prettyprinter} This the actual prettyprinter. We'll use a [[struct]] to conform with the API. A [[class]] would be nicer though. Inside the prettyprinter we have to store the callback function and the [[closure]] parameter, which is a kind of user data. Also, we need a [[strstream]] object to collect all the strings coming in. <>= struct prettyprinter { PrettyPrinterCallback ppcb; void* user_data; strstream* to_be_pped; /* space for collecting code */ }; @ <
>= #include @ \subsection{The Prettyprinter Functions} To create a new prettyprinter for a chunk, we simply create a new [[PrettyPrinter]] object and store the interesting stuff in the right places. (Sorry, this is C++, but we're using [[iostreams]] anyway.) <>= PrettyPrinter new_prettyprinter( PrettyPrinterCallback callback, void* closure) { PrettyPrinter pp = (PrettyPrinter) malloc(sizeof(struct prettyprinter)); pp->ppcb = callback; pp->user_data = closure; pp->to_be_pped = new strstream; return(pp); } @ <
>= #include @ Now for the actual [[prettyprint]] function. Its task is to prettyprint the incoming strings and send them back to the application via the callback. Internally, [[prettyprint]] is a giant switch. It looks at the type of thing that is coming in and decides what to to. <>= void prettyprint(PrettyPrinter pp, Parttype type, char *contents) { switch (type) { <> default : cerr << "Oops. There's a parttype I don't understand." << endl; exit(1); } } @ Now let's look at the different cases. We know from the start that the case of [[END_OF_CHUNK]] will be the most complicated, because all work is done there. So let's leave this until the end. We'll have the simple cases first, e.g.~the [[STRING]] case. @ When [[type==STRING]], the incoming string is a bit of code that needs to be mangled and thus simply appended to the [[strstream]] within the prettyprinter. <>= case STRING : *(pp->to_be_pped) << contents; break; @ A similar thing is done when a [[NEWLINE]] arrives. <>= case NEWLINE : *(pp->to_be_pped) << "\n"; break; @ Now for one of the tricky bits, the [[USE_CHUNK]] case. Normally, we would call the callback with the chunk name at that moment, when the prettyprinted text before the chunk name has been output (via the callback) and before the text following it is output. Unfortunately, in the current version of Pretzel, we do not have real control where the chunk name appears in the output and thus don't have an obvious chance of calling the callback directly here. We use a trick here: We know that we'll chop up the prettyprinted output into lines and output these lines one at a time later on. So we'll put a full line of text referring to the chunk into the prettyprinted output. This line has to be spotted by the prettyprinter and left unchanged. When the prettyprinter has done his work, we'll check all the lines for their starting characters and call the callback with [[type==USE_CHUNK]] if a line starts with [[@use]]. <>= case USE_CHUNK : *(pp->to_be_pped) << "\n@use " << contents << "\n"; break; @ The last case for now is the [[WHATSIT]] case. These things can be ignored by the pretzel prettyprinter but they will nevertheless have to be mangled by it. We follow the same plan as above and add the incoming line to the string that is to be prettyprinted. The prettyprinter has to spot this line and leave it unchanged. We assume that these lines have an [[@]] sign at their beginning. <>= case WHATSIT : *(pp->to_be_pped) << "\n" << contents << "\n"; break; @ \begin{center} \large\bf The following chunks contains the only changes to {\tt prettycee.nw}. \end{center} If an [[END_OF_CHUNK]] is received, we expect it to be the last call to the current prettyprinter. All code sent to us before has to be prettyprinted now and output through the callback to the application. This is where the Pretzel function comes into action. Say, we have a Pretzel prettyprinter for your favourite programming language. We need to include its header to be able to use it. As we don't want to use the default output type (which is \LaTeX), we have to include the special {\sc ASCII} output header file. <
>= #include "Ppparse.h" #include "asciioutput.h" @ Ok, now we can outline the case. In general, we'll top off the string and feed it to the [[prettyprint]] function. This will return stuff on an [[ostream]], which is replaced again by a [[strstream]] by us. We can assume that line breaks and so on have been inserted into the output stream by the [[ascii_terminal_output]] already so it's okay to output line by line. <>= case END_OF_CHUNK : { strstream has_been_pped; Ppparse pretzelpp; *(pp->to_be_pped) << ends; /* end up the string */ /* pretzelpp.debug_on(); */ Ascii_terminal_output ascii_outp(has_been_pped); pretzelpp.prettyprint( pp->to_be_pped, &ascii_outp ); <> } break; @ Chopping the stuff inside [[has_been_pped]] into lines is not very nice, but feasible. Is there a way to do it more elegantly using the `[[<<]]' operator? For the time being we'll use the [[strtok]] function from the {\tt string.h} header file. <
>= #include @ The text which comes from the prettyprinter will probably not look faintly as nice as the original code: Special macros will be added (in the \LaTeX{} case), indentation will have changed, identifiers may have swapped places. This is why we'll send the individual lines as [[LITERAL]] lines to the application. It will ensure that the line will not get mangled further by {\tt noweb} back ends. If we encounter a line beginning with [[@]], this is a line to be sent to the application directly. Assuming that the above lines haven't been changed by the prettyprinter, this case will cover the [[USE_CHUNK]] case as well as all other cases of {\tt noweb} keywords. <>= char* entire_pped_code = has_been_pped.str(); char* line = strtok(entire_pped_code, "\n"); do { if (strlen(line) == 0) { (pp->ppcb)(pp->user_data, NEWLINE, NULL); continue; } if (*line == '@') { (pp->ppcb)(pp->user_data, WHATSIT, line); } else { (pp->ppcb)(pp->user_data, LITERAL, line); (pp->ppcb)(pp->user_data, NEWLINE, NULL); } } while ( (line = strtok( NULL, "\n" )) != NULL ); @ Finally, it's our responsibility to cleanup the output [[strstream]], because we've called the [[str()]] function on it. <>= delete entire_pped_code; @ \end{document} % % $Log: prettycee2html.nw,v $ * Revision 1.1 1996/12/16 18:53:15 gaertner * Initial revision * % % pretzel-2.0n-2/contrib/noweb/cee.html/cee2html.ft0000644000000000000000000000511006255315416020366 0ustar rootroot/* cee2html.ft - pretzel formatted token file for simple C * * target formatter: HTML * * based on c.ft (which has target formatter LaTeX) * * $Id: cee2html.ft,v 1.1 1996/12/16 18:53:15 gaertner Exp $ * * History at end. */ ALPH [a-zA-Z] ALPHNUM [a-zA-Z0-9\_] ALPHNUMDOT [a-zA-Z0-9\.] NUM [0-9] %% // unary or binary operators for math mode "+" | "-" | "*" UNORBINOP "/" | "<" UNORBINOP { "<" } "=" UNORBINOP ">" UNORBINOP { ">" } "." | "|" BINOP "%" BINOP "?" QUESTION "!" UNOP "~" UNOP "&" UNORBINOP { "&" } "," COMMA "(" LPAR "[" LPAR ")" RPAR "]" RPAR "{" LBRACE "}" RBRACE ";" SEMI ":" COLON "++" UNOP "--" UNOP // binary operators for math mode "!=" BINOP "<=" BINOP { "<=" } ">=" BINOP { ">=" } "==" BINOP "&&" BINOP { "&&" } "||" BINOP "->" BINOP ">>" BINOP { ">>" } "<<" BINOP { "<<" } "::" UNORBINOP // preprocessor directives: "#" INSERT "#include" | "#ifdef" | "#ifndef" | "#undef" | "#elif" | "#error" | "#pragma" | "#endif" LPROC { "" + ** + "" } "this" | "NULL" NUMBER // reserved words: // types and alike: "auto" | "char" | "const" | "double" | "extern" | "FILE" | "float" | "int" | "long" | "register" | "short" | "static" | "unsigned" | "volatile" | "void" | "friend" | "inline" | "virtual" | "signed" INT_LIKE { "" + ** + "" } "enum" | "union" | "class" | "struct" STRUCT_LIKE { "" + ** + "" } "delete" | "new" | "operator" | "sizeof" SIZEOF_LIKE { "" + ** + "" } "define" DEFINE_LIKE { "" + ** + "" } // case statement handling: "break" | "case" | "continue" | "default" | "private" | "protected" | "public" | "template" | "return" CASE_LIKE { "" + ** + "" } "switch" IF_LIKE { "" + ** + "" } // control structures: "do" DO_LIKE { "" + ** + "" } "else" ELSE_LIKE { "" + ** + "" } "for" | "if" | "while" IF_LIKE { "" + ** + "" } // type constructors "typedef" TYPEDEF_LIKE { "" + ** + "" } // comments: "/*"[^\*]*"*/" INSERT \'.\' STRING // strings \"[^\"]*\" STRING "<"{ALPHNUMDOT}+">" LPROC { "\n@literal \\verb|" ** "|\n" } // chunks and other stuff for noweb: ^"@use\ ".* CHUNK { "\n" + ** + "\n" } ^"@".* IGNORE { "\n" + ** + "\n" } {ALPH}{ALPHNUM}* ID {NUM}+ NUMBER [\ \t\n] // gobble up whitespace . // forget all non-standard characters // somehow some strange characters are // sent to pretzel (TODO). forget them. %% /* * $Log: cee2html.ft,v $ * Revision 1.1 1996/12/16 18:53:15 gaertner * Initial revision * * */ pretzel-2.0n-2/contrib/noweb/cee.html/cee2htmltest-sample.html0000644000000000000000000001760006255314447023112 0ustar rootroot cee2htmltest.nw This is a small file ment to test the noweb prettyprinting filter for C and HTML.

Fist some simple noweb stuff.

<*>=
<a chunk>

An empty chunk.

<a chunk>=
<a chunk>

<a chunk>+=
<another chunk><and still another chunk>

Now let's start with some C stuff.

<some variable declarations>=
int an_int,
another_int,
and_still_another_int;
char c,
d;
float a,
b;
float pi;
double a,
b,
c,
e,
f,
g;

<some modified variable declarations>=
short i1;
short int i2;
long i3;
long int i4;
long double doublette;
unsigned int big_one;
signed char odd_one;

<some initialized variables>=
int i=1234;
int a,
b,
i,
g,
l,
o,
n,
g,
r,
o,
w,
o,
f,
in,
t,
e,
g,
e,
r,
s;
long l=123456789L;

Let's try some octal and other esoteric stuff.

<some more initialized variables>=
float f1=123.4,
f2=1 e-2,
f3=1;
int octal_int=0777;

The first line is an unsigned long with value 15.

<some more initialized variables>+=
int hex_int=0x1f;
float pi=3.141,
pi2;
long hex_long=0XFUL;
char initialized_char='c',
another_one='x',
difficult_ones=n,
another_difficult_one=777,
bell=007;

<some constants>=
const float e=2.71828182845905;
const char msg[]="warning: ";i>;

Now for some pointers and arrays.

<some pointers>=
int *ip;
int int_array[];
int int_array[1000];
char *a_string;
char **an_array_of_strings;
char *s="a string!";
int ****hey;
int ****hey_hoh;
int *zero=NULL;

<some big initializers>=
int_array[]int_array[];

Now for some operators.

<some operators>=
x+x;
x-x;
x*x;
x<x;
x%x;
x<y;
x<=y;
x>=y;
x>y;
x==y;
x!=y;
x&y;
x&&y;
x|y;
x||y;
~x;
++x;
x++;
--x;
x--;
x+=2;
x-=2;
x*=2;
x<=2;

<conditional expressions>=
a/i>-x;

<referncing and derefencing>=
p=&i;
c=*a;
cc=a->b;
ccc=a.b;

\section{Control Flow}

<some conditionals>=
if (a==1)s=1;
elses=2;
if (a)  

<happy if's>=
if (a!=0)
  {
    b=1;
    c=2;
  }
  if (n>0)if (a>b)z=a;
      elsez=b;
      
    
  

<some else-if's>=
if (a==b)s1();
  elseif (a!=b)s2();
      elses3();
      
    
  

<switch and alike>=
switch (a)
  {
    case 1:s1;
    break;
    case 2:s2;
    break;
    default:s3;
  }
  

<some loops>=
for(i=0;isspace(s[i]);i++);;) {
  do_forever = 1;
}
while (c < 100) c++;
while (c<1000

<labels and goto>=
for(i=1;i<10;i++)
  {
    if (disaster)goto error;
    
  }
  
error:i=42;

Constructed Types

Types defined by typedef should be handled like normal types and be typeset just like them.

<a few typedefs>=
typedef int Length;
typedef char *String;
Length len;
Length len,
maxlen;

Let's see if if works in another chunk too.

<a few typedefs>+=
String a_string;
Length first=100;

Hard Stuff

<Chop resulting text into lines and send them to application>=
char *entire_pped_code=has_been_pped.str();
(pp->ppcb)(pp->user_data,
STRING,
" ");
(pp->ppcb)(pp->user_data,
LITERAL,
"\\begin{ppcode}");
char *line=strtok(entire_pped_code,
"\n");
do
{
  if (strlen(line)==0)
    {
      (pp->ppcb)(pp->user_data,
      NEWLINE,
      NULL);
      continue;
    }
    if (*line=='@')
      {
        (pp->ppcb)(pp->user_data,
        WHATSIT,
        line);
      }
      else
        {
          (pp->ppcb)(pp->user_data,
          LITERAL,
          line);
          (pp->ppcb)(pp->user_data,
          NEWLINE,
          NULL);
        }
        
      
    
  
}
while ((line=strtok(NULL,
"\n"))!=NULL);
(pp->ppcb)(pp->user_data,
LITERAL,
"\\end{ppcode}");

Finally, it's our responsibility to cleanup the output strstream, because we've called the str() function on it.

<Chop resulting text into lines and send them to application>+=
delete entire_pped_code;/i>.str();
(pp->ppcb)(pp->user_data,
STRING,
" ");
(p

Some more hard stuff (taken from t1.w).

<main>=
mlp=NULL;
/* init match list pointer */
mp=mlp;
hp=rp->right;
/* point |hp| to beginning of round list */
while (hp!=NULL)
  {
    if (hp->type==matches)
      {
        if (mp==NULL)
          {
            /* take this node as hew head */
            mp=new_node();
            check_node(mp);
            mp->type=matches;
            mp->right=hp->right;
            mp->left=NULL;
            /* terminate list */
            mlp=mp;
          }
          else
            {
              /* add this one to the back */
              mp->left=new_node();
              check_node(mp->left);
              mp=mp->left;
              mp->type=matches;
              mp->right=hp->right;
              mp->left=NULL;
              /* terminate list */
            }
            
          
        
      }
      hp=hp->left;
      /* look at next item of the list */
    
  }
  

That's it.

pretzel-2.0n-2/contrib/noweb/java.latex/0000755000000000000000000000000006537735117016700 5ustar rootrootpretzel-2.0n-2/contrib/noweb/java.latex/index.list0000644000000000000000000000051206360655624020700 0ustar rootrootthis directory & a noweb prettyprinter for Java Hanoi-pretty.dvi & example output using Hanoi.nw as input Hanoi.nw & Example Java noweb input: The towers of Hanoi with four sticks Makefile & The Makefile README & more information javafx.fg & formatted grammar for Java with noweb javafx.ft & formatted tokens for Java with noweb pretzel-2.0n-2/contrib/noweb/java.latex/javafx.ft0000644000000000000000000001500106537734440020505 0ustar rootroot/* * javafx.ft -- experimental Pretzel token file for Java * * based on original version by Lee Wittenberg and enhanced * for use with noweb * * History at end * * $Header$ * */ ALPH [a-zA-Z_$] ALPHNUM [a-zA-Z0-9_$] DIGIT [0-9] DECDIGIT [0-9] OCTDIGIT [0-7] HEXDIGIT [0-9A-Fa-f] EXP ([eE][+-]?[0-9]+) %{ #include // forward declaration of a function that replaces `_' // with `\_' in a copy of s (don't need it here though) static char* escaped_underlines(char* s); %} %% // // symbols "{" LBRACE {"\\{"} "}" RBRACE {"\\}"} "(" LPAR ")" RPAR "[" LBRACK "]" RBRACK ";" SEMI {"\\mathout; "} ":" COLON {":"} "," COMMA {"\\mathout, "} "." DOT {"{.}"} "+" | "-" UNORBINOP "=" BINOP {"\\gets"} "<" | ">" BINOP "!" UNOP {"\\lnot"} "~" UNOP {"\\~{}"} // Lee said: {"\\mathord{\\sim}"} "?" QUESTION {"\\mathrel?"} "==" BINOP {"\\equiv"} "<=" BINOP {"\\leq"} ">=" BINOP {"\\geq"} "!=" BINOP {"\\neq"} "||" BINOP {"\\lor"} "&&" BINOP {"\\land"} "++" | "--" INCROP {"\\mbox{\\tt" + ** + "}"} "*" BINOP {"\\times"} "/" BINOP {"\\div"} "&" BINOP {"\\mathrel{\\&}"} "|" BINOP {"\\mid"} "^" BINOP {"\\oplus"} "%" BINOP {"\\mathbin{\\%}"} "<<" BINOP {"\\ll"} ">>" BINOP {"\\gg"} ">>>" BINOP {"\\ggg"} // needs amssymb package "+=" BINOP {"\\buildrel\\;+\\over{\\gets}"} "-=" BINOP {"\\buildrel\\;-\\over{\\gets}"} "*=" BINOP {"\\buildrel\\;\\times\\over{\\gets}"} "/=" BINOP {"\\buildrel\\;\\div\\over{\\gets}"} "&=" BINOP {"\\buildrel\\;\\&\\over{\\gets}"} "|=" BINOP {"\\buildrel\\;\\mid\\over{\\gets}"} "^=" BINOP {"\\buildrel\\;\\oplus\\over{\\gets}"} "%=" BINOP {"\\buildrel\\;\\%\\over{\\gets}"} "<<=" BINOP {"\\buildrel\\;\\ll\\over{\\gets}"} ">>=" BINOP {"\\buildrel\\;\\gg\\over{\\gets}"} ">>>=" BINOP {"\\buildrel\\;\\ggg\\over{\\gets}"} // needs amssymb package // try to mimic CWEB explicit format commands: "//@/" | "//@force" IGNORE { force } "//@#" | "//@big_force" IGNORE { big_force } "//@cancel" IGNORE { cancel } "//".* COMMENT {"\\mbox{" ** "}" force } // // keywords "new" UNOP {"\\mbox{\\bf " + ** + "}\\ "} "instanceof" BINOP {"\\in"} // alternate: {"\\mathrel{\\mbox{\\bf " + ** + "}}"} // make INT_LIKE (not ID_LIKE) to avoid indexing: "null" INT_LIKE {"\\mathin\\Lambda"} "class" CLASS "interface" CLASS "boolean" | "byte" | "char" | "double" | "float" | "int" | "long" | "String" | // is also a simple type! "short" INT_LIKE {"\\mbox{\\bf " + ** + "}"} // to catch void function definitions // (Lee said: ID_LIKE) "void" INT_LIKE {"\\mbox{\\bf " + ** + "}"} // modifiers were ID_LIKE, make them INT_LIKE to avoid indexing "abstract" | "final" | "native" | "protected" | "private" | "public" | "static" | "transient" | "volatile" INT_LIKE { "\\mbox{\\bf " ** "}" } "true" | "false" | "super" | // for Lee, all these were ID_LIKE. "this" INT_LIKE {"\\mbox{\\bf " + ** + "}"} "case" CASE_LIKE {"\\mbox{\\bf " + ** + "}"} "default" DEFAULT_LIKE {"\\mbox{\\bf " + ** + "}"} "synchronized" SYNC_LIKE {"\\mbox{\\bf " + ** + "}"} "try" TRY_LIKE {"\\mbox{\\bf " + ** + "}"} "catch" CATCH_LIKE {"\\mbox{\\bf " + ** + "}"} "finally" FINALLY_LIKE {"\\mbox{\\bf " + ** + "}"} "if" | "switch" | "while" IF_LIKE {"\\mbox{\\bf " + ** + "}"} "else" ELSE_LIKE {"\\mbox{\\bf " + ** + "}"} "for" FOR_LIKE {"\\mbox{\\bf " + ** + "}"} "do" DO_LIKE {"\\mbox{\\bf " + ** + "}"} "break" | "continue" | "return" | "throw" BREAK_LIKE {"\\mbox{\\bf " + ** + "}"} "throws" | "extends" | "implements" EXTENDS_LIKE {"\\mbox{\\bf " + ** + "}"} "package" | "import" IMPORT_LIKE {"\\mbox{\\bf " + ** + "}"} ".*" DOT_STAR { ".*" } // Lee said: {"\\mathin.\\mathord{\\ast}"} // // misc ^"@use\ ".* CHUNK { "\n" + ** + "\n" } ^"@".* IGNORE { "\n" + ** + "\n" } 0[lL]? | [1-9]{DECDIGIT}*[lL]? | 0{OCTDIGIT}+[lL]? | 0[xX]{HEXDIGIT}{HEXDIGIT}*[lL]? | {DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]? | "."{DECDIGIT}+{EXP}?[fdFD]? | {DECDIGIT}+{EXP}[fdFD]? NUM // identifiers are passed `as is' to the parser. // We could escape underlines here, but we'll better leave // that to the parser. // a distinction between short ids and long ids is made to spare // short identifiers from getting into the index. This is done // here because it's easiest to check the length here. SHORT_IDs // will be treated just like ID_LIKEs from now on except indexing. {ALPH} SHORT_ID {ALPH}{ALPHNUM}* ID_LIKE '([^']|\\')*' | \"([^\"]|\\\")*\" STRING {"\\verb*\013" + ** + "\013"} [\ \t\n] // gobble up whitespace . // ignore all non-standard chars // (bug in Pretzel?) %% // escaped_underines replaces every occurrence of `_' by // the two characters `\_' in a copy of the string pointed to // by s // // the implementation first counts the number of underlines in // the string s and allocates new memory for the string. It then // copies the string byte after byte into the new place and // takes care to insert a `\' before any underline. // // this is a bit dirty as we don't have a chance to free the // allocated space later on, but it's still better than messing // around with yytext. To minimize the amount of memory I have // added a test whether copying is needed or not. static char* escaped_underlines(char* s) { char* tmp = s; int number_of_ul = 0; int left = 0; // s[left] is the next char to copy int right = 0; // place s[left] in tmp[right] // fprintf(stderr, "call of escaped_underlines\n"); // count underlines in s while (*tmp != 0) { if (*tmp == '_') number_of_ul++; tmp++; } // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul); if (number_of_ul == 0) { tmp = s; // skip copying } else { tmp = new char[strlen(s) + number_of_ul + 1]; assert(tmp!=NULL); // now start to copy while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but // some compilers choke on it if (s[left] == '_') { tmp[right] = '\\'; right++; } tmp[right] = s[left]; left++; right++; } tmp[right] = s[left]; /* terminate string */ } // fprintf(stderr, "escaped_underlines: in: %s, out: %s\n", s, tmp); return(tmp); } /* * $Log: javafx.ft,v $ * Revision 1.1 1997/07/09 14:24:27 gaertner * Initial revision * * Revision 1.2 1997/07/08 18:48:34 theedge * Versions that work. * * Revision 1.1 1997/06/26 16:23:56 theedge * Initial revision * */ pretzel-2.0n-2/contrib/noweb/java.latex/README0000644000000000000000000000231106360655331017546 0ustar rootrootA pretty good prettyprinter that works with Java and noweb (in LaTeX mode). After installing Pretzel, try typing `make' here. This will weave and prettyprint Hanoi.nw, a Java implementation of the towers of Hanoi with four landing places. To prettyprint your own stuff, try: noweave -delay -filter prettyjava -index file.nw > file.tex Your document should use the pretzel-noweb LaTeX package and look a little like this: \documentclass{article} \usepackage{noweb} \usepackage{pretzel-noweb} % \begin{document} ... % rest of the noweb file \end{document} Note that you have to usepackage pretzel-noweb _after_ noweb and issue -filter prettyjava _before_ the -index switch on the command line. You can use format commands in the source code a la CWEB, e.g. you can say: stuff //@/ or stuff //@force (both act like a `force' format command) and you can say stuff //@cancel to issue a non-standard `cancel'. More can be built in quite easily. Problems: - class names are typeset in bold only after they have been defined. - Indexing is a little confusing sometimes and needs some fine tuning (especially distinguishing definition and use) What do you think? pretzel-2.0n-2/contrib/noweb/java.latex/index.html0000644000000000000000000000230706360655633020675 0ustar rootroot Index file for directory "pretzel/contrib/noweb/java.latex" of Pretzel distribution

Index file for directory "pretzel/contrib/noweb/java.latex" of Pretzel distribution

Files and directories are:

this directory

    a noweb prettyprinter for Java
Hanoi-pretty.dvi
    example output using Hanoi.nw as input
Hanoi.nw
    Example Java noweb input: The towers of Hanoi with four sticks
Makefile
    The Makefile
README
    more information
javafx.fg
    formatted grammar for Java with noweb
javafx.ft
    formatted tokens for Java with noweb

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 11:36:28 MESZ 1997 pretzel-2.0n-2/contrib/noweb/java.latex/Makefile0000644000000000000000000000057606360655425020345 0ustar rootroot Hanoi.dvi: Hanoi.tex latex Hanoi.tex latex Hanoi.tex Hanoi.tex: prettyjava Hanoi.nw noweave -delay -filter prettyjava -index Hanoi.nw > Hanoi.tex prettyjava: javafx.ft javafx.fg pretzel-it -n javafx prettyjava clean: rm -f Hanoi.aux Hanoi.toc Hanoi.log Hanoi.tex \ javafx.lex.* javafx.tab.* javafx.y javafx.l ptokdefs.h clobber: clean rm -f prettyjava Hanoi.dvi pretzel-2.0n-2/contrib/noweb/java.latex/Hanoi-pretty.dvi0000644000000000000000000005705006360653176021774 0ustar rootroot÷ƒ’À;è TeX output 1997.07.09:1114‹ÿÿÿÿ y ý£ ? þ’’¢éóDÓítG®G®cmr17ºT‘þ¥Vo•Œqw“ers–7tof“Hanoi“revisitedŽŸ’Çò óX«Q cmr12»F‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸˆ‹’Ë?èJuly–ê¨9,“1997ŽŸ+Ä‘>óÂÖN ff cmbx12ÅCon•ŒÌten“tsޤ‘>óò"V cmbx10Æ1Ž‘MIn®9troQÇduction’Øú1ŽŽ¡‘>2Ž‘MAnimated‘ÕTHanoi’ðé6ŽŽ¤ ‘MóKñ`y cmr10²2.1Ž‘dUsing‘8˜‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘¢6ŽŽ¡‘M2.2Ž‘dImplemen¸ãtation‘ÿˆ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘¢7ŽŽ¤‘>Æ3Ž‘MList–ÕTof“Re nemen®9ts’Ü’þ10ŽŽ¡‘>4Ž‘MIndex’"b10ŽŽŸ!Ä‘>Å1Ž‘VLËInŒÌtros3ductionŽŸç‘>²A‘×c\to•¸ãw“ers–×…of“hanoi"“implemenš¸ãtation“with“four“landing“places“for“bric˜ks.‘øVThisޤ ‘> le–ûîwš¸ãas“written“using“the“óßê le–UUfrom“this“text,“run“¹notangle“²on“it.ŽŽŸ’è1ŽŽŒ‹* y ý£ ? ýä‘M²Here's–ç the“frame“of“it“all.‘&ðAll“stu “is“included“within“the“¹Hanoi“²class,‘ {i.e.ޤ ‘>also–UUthe“auxiliary“functions“lik¸ãe“¹assert².Ž©‘Ñ”ó|{Ycmr8¼2aŽ‘>ó !",š cmsy10¸hóý': cmti10ÇHanoi.java‘“ç¼2a¸iŽ’'ÈŽ¡‘H²//›UUto•¸ãw“ers˜of˜hanoi˜with˜four˜bGo“xesŽŽ¡‘HÆclassŽ‘bMHanoiŽ’ƒŽ×¸fŽ¡‘RhÇHanoi–“çclass“variables“¼2b¸iŽŽ¡‘UUVhÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iŽ’ØÈcÆstaticŽ’÷~v®9oidŽ’èªÇassert²(Æb•QÇo“oleanŽ‘*N*Çt²)‘UU¸fŽ¡‘\ÆifŽ‘f ª²(¸:ÇtŽŽ‘ ïÿ²)‘UU¸fŽ¡‘fÇSystemŽ’…oó  b> cmmi10µ:ÇerrŽ‘µ:ÇprintlnŽ‘H›²(¹"Assertion violation"Ž‘n?Á²);Ž¡‘fÇSystemŽ’…oµ:ÇexitŽ‘“‡²(1);Ž¡‘\¸gŽ¡‘RgŽ¡‘HgŽŸ €‘>¼De nes:ޤ €‘Hó"ßCÊscmtt8ÍHanoi¼,–ÕXnevÃŽer“used.Ž¡‘HÍSystem¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍassert¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍerr¼,–ÕXnevÃŽer“used.Ž¡‘HÍprintln¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍt¼,–ÕXused“in“c•ÃŽh“unk‘ÕX9a.Ž¡‘>Uses‘ÕXÍexit¼.ަ‘M²The›/þmo•¸ãv“es˜that˜ha“v“e˜bGeen˜tak“en˜b“y˜this˜algorithm˜are˜coun“ted˜in˜¹moves².ޤ ‘>Also,–UUwš¸ãe“can“use“a“¹HanoiView“²ob‘Ž8ject“to“ha˜v˜e“a“loGok“at“what's“going“on.ަ‘X°¼2bŽ‘>¸hÇHanoi–“çclass“variables“¼2b¸iŽ’®8ÄŽ¡‘HÆstaticŽ‘fµ¤in®9tŽ‘wÇfÇmovesŽ’•ô}¸ ‘Dz0;Ž¡‘HÆstaticŽ‘fµ¤ÇHanoiViewŽ’›55viewŽ’±ù¸ ‘Dz;ŽŸ €‘>¼De nes:ޤ €‘HÍHanoiView¼,–ÕXused“in“c•ÃŽh“unks–ÕX5“and“7b.Ž¡‘HÍmoves¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍview¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.ŽŽŸ’è²2ŽŽŒ‹ y ý£ ? ýä‘M²All–¹·stu “will“bGe“brokš¸ãen“do˜wn“to“calls“of“this“function.‘žîIt“is“an“in˜terface“toޤ ‘>pšGossible–UUvisualization“to˜ols.‘qÇW‘ÿ*ªe'll“counš¸ãt“the“mo˜v˜es“here.ŽŸ‘Ñ”¼3aŽ‘>¸hÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iŽ’¾¸Ž¡‘HÆstaticŽ‘fµ¤v®9oidŽ‘ GÇmoveŽ’–]À²(Æin®9tŽ‘ÂÇfr‘ÿ}'omŽ‘%åÁ²,‘UUÆin®9tŽ‘gÇtoŽ‘wš²)‘UU¸fŽ¡‘RÇmovesŽ‘mf¹++ŽŽ‘wåú²;Ž¡‘RÆifŽ‘\ ©²(ÇmovesŽ‘-µ>‘ÇÇb‘ÿ}'oring‘|‰ffŽ‘|sizeŽ‘2C²)–UU¸f‘²//“only“output“spšGoradic“progress“rep˜ortsŽŽ¡‘\ÆifŽ‘f ª²(ÇmovesŽ‘žß²%‘8àÇb–ÿ}'oring‘|‰ffŽ‘|size‘Yó‰ffŽ‘Yõslic“eŽ‘K‰u¸‘Dz0)‘UU¸fŽ¡‘fÇSystemŽ’…oµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(¹"Finished "Ž–;ø¿²+‘8àÇmovesŽ‘׿²+‘8à¹". move..."Ž“²);Ž¡‘\¸gŽ¡‘Rg‘UUÆelseŽ‘ðT¸fŽ¡‘\ÇSystemŽ‘{oµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(¹"Moving from "Ž‘K¸¶²+‘8àÇfr‘ÿ}'omŽ‘E¿²+‘8à¹" to "Ž‘#ñ®²+‘8àÇtoŽ‘ ‚C²+‘8à¹"... ("Ž‘)1«²+‘8àÇmovesŽ‘׿²+‘8à¹". move)"Ž‘1xŲ);Ž¡‘\ÆifŽ‘f ª²(ÇviewŽ‘ÃÛ¸6²=‘Ç)Ž¡‘fÇviewŽ‘yüƵ:ÇmoveŽ‘=y²(Çfr‘ÿ}'omŽ‘Óÿ²,‘UUÇtoŽ‘ eز);Ž¡‘R¸gŽ¡‘HgŽ© €‘>¼De nes:ޤ €‘HÍfrom¼,–ÕXnevÃŽer“used.Ž¡‘HÍmove¼,–ÕXused“in“c•ÃŽh“unk‘ÕX4a.Ž¡‘HÍmoves¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍto¼,–ÕXnevÃŽer“used.Ž¡‘HÍview¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘>Uses–ÕXÍSystem“¼2a“5“6“8,“Íboring_size“¼3b,“Íboring_size_slice“¼3b,“Íout¼,“and“Íprintln“¼2a“5“6.ŽŸ‘X°3bŽ‘>¸hÇHanoi–“çclass“variables“¼2b¸iŽ’®8IJ+Ž’µÿâ¸ŽŽ¤ ‘HÆstaticŽ‘fµ¤ nalŽ‘šðin®9tŽ’¬²Çb‘ÿ}'oring‘|‰ffŽ‘|sizeŽ’Ã<õ¸ ‘Dz100;Ž¡‘HÆstaticŽ‘fµ¤ nalŽ‘šðin®9tŽ’¬²Çb–ÿ}'oring‘|‰ffŽ‘|size‘Yó‰ffŽ‘Yõslic“eŽ’ÙýG¸ ‘Dz100;ަ‘>¼De nes:ޤ €‘HÍboring_size¼,–ÕXused“in“c•ÃŽh“unk‘ÕX3a.Ž¡‘HÍboring_size_slice¼,–ÕXused“in“c•ÃŽh“unk‘ÕX3a.ŽŽŸ’è²3ŽŽŒ‹ j y ý£ ? ýä‘M²Here's–`”the“old“\straighš¸ãt“out“of“the“hat"“implemen˜tation“of“the“to˜w˜ers“usingޤ ‘>only–UUthree“bGoš¸ãxes.‘qÇIt“w˜on't“use“the“¹without“²bGo˜x.Ž©‘Ñ”¼4aŽ‘>¸hÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iŽ’¾¸²+Ž’ÅäÖ¸ŽŽ¡‘HÆstaticŽ‘fµ¤v®9oidŽ‘ GÇhanoi‘žr‰ffŽ‘žtoldŽ’©”²(Æin®9tŽ‘ÂÇhow‘­%‰ffŽ‘­'manyŽ‘?Cy²,‘UUÆin®9tŽ‘gÇfr‘ÿ}'omŽ‘);²,‘UUÆin®9tŽ‘gÇtoŽ‘wš²,‘UUÆin®9tŽ‘gÇuseŽ‘#5¥²,‘UUÆin®9tŽ‘gÇwithoutŽ‘5K©²)‘UU¸fŽ¡‘RÇassertŽ‘l`P²(Çfr‘ÿ}'omŽ‘ ß²+‘8àÇtoŽ‘ ‚C²+‘8àÇuseŽ‘@N²+‘8àÇwithoutŽ‘%䊸‘Dz10);Ž¡‘RÆifŽ‘\ ©²(Çhow‘­%‰ffŽ‘­'manyŽ‘0øÏ¸‘Dz1)‘UU¸fŽ¡‘\ÇmoveŽ‘s={²(Çfr‘ÿ}'omŽ‘Óÿ²,‘UUÇtoŽ‘ eز);Ž¡‘R¸g‘UUÆelseŽ‘ðT¸fŽ¡‘\Çhanoi‘žr‰ffŽ‘žtoldŽ’†s¿²(Çhow‘­%‰ffŽ‘­'manyŽ‘0j—¸‘8à²1,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇuseŽ‘#ã²,‘UUÇtoŽ‘ eز,‘UUÇwithoutŽ‘$9ç²);Ž¡‘\ÇmoveŽ‘s={²(Çfr‘ÿ}'omŽ‘Óÿ²,‘UUÇtoŽ‘ eز);Ž¡‘\Çhanoi‘žr‰ffŽ‘žtoldŽ’†s¿²(Çhow‘­%‰ffŽ‘­'manyŽ‘0j—¸‘8à²1,‘UUÇuseŽ‘#ã²,‘UUÇtoŽ‘ eز,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇwithoutŽ‘$9ç²);Ž¡‘R¸gŽ¡‘HgŽŸ €‘>¼De nes:ޤ €‘HÍassert¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍfrom¼,–ÕXnevÃŽer“used.Ž¡‘HÍhanoi_old¼,–ÕXused“in“c•ÃŽh“unk‘ÕX4b.Ž¡‘HÍhow_many¼,–ÕXnevÃŽer“used.Ž¡‘HÍto¼,–ÕXnevÃŽer“used.Ž¡‘HÍuse¼,–ÕXnevÃŽer“used.Ž¡‘HÍwithout¼,–ÕXnevÃŽer“used.Ž¡‘>Uses–ÕXÍmove“¼3a“3a“8.ަ‘M²The–±çidea“bšGehind“this“four“b˜oš¸ãx“implemen˜tation“is“to“mo˜v˜e“slices“of“µk‘~²bric˜ksޤ ‘>at–UUa“time.‘qÇThe“fourth“bGoš¸ãx“is“used“to“enable“building“these“µkP—²-bric˜k“bric˜ks.ަ‘X°¼4bŽ‘>¸hÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iŽ’¾¸²+Ž’ÅäÖ¸ŽŽ¡‘HÆstaticŽ‘fµ¤v®9oidŽ‘ GÇhanoi‘žr‰ffŽ‘žtfourŽ’®šÁ²(Æin®9tŽ‘ÂÇhow‘­%‰ffŽ‘­'manyŽ‘?Cy²,‘UUÆin®9tŽ‘gÇfr‘ÿ}'omŽ‘);²,‘UUÆin®9tŽ‘gÇtoŽ‘wš²,‘UUÆin®9tŽ‘gÇuseŽ‘#5¥²,‘UUÆin®9tŽ‘gÇwithoutŽ‘5K©²,‘UUÆin®9tŽ‘gÇk‘²)‘UU¸fŽ¡‘RÇassertŽ‘l`P²(Çfr‘ÿ}'omŽ‘ ß²+‘8àÇtoŽ‘ ‚C²+‘8àÇuseŽ‘@N²+‘8àÇwithoutŽ‘%䊸‘Dz10);Ž¡‘RÆifŽ‘\ ©²(Çhow‘­%‰ffŽ‘­'manyŽ‘0øÏ¸‘ÇÇk‘²)‘UU¸fŽ¡‘\Çhanoi‘žr‰ffŽ‘žtoldŽ’†s¿²(Çhow‘­%‰ffŽ‘­'manyŽ‘.1·²,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇtoŽ‘ eز,‘UUÇwithoutŽ‘$9ç²,‘UUÇuseŽ‘#ã²);Ž¡‘R¸g‘UUÆelseŽ‘ðT¸fŽ¡‘\Çhanoi‘žr‰ffŽ‘žtfourŽ’‹z|²(Çhow‘­%‰ffŽ‘­'manyŽ‘0j—¸‘8àÇk–²,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇuseŽ‘#ã²,‘UUÇtoŽ‘ eز,‘UUÇwithoutŽ‘$9ç²,‘UUÇk“²);Ž¡‘\Çhanoi‘žr‰ffŽ‘žtoldŽ’†s¿²(Çk‘²,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇtoŽ‘ eز,‘UUÇwithoutŽ‘$9ç²,‘UUÇuseŽ‘#ã²);Ž¡‘\Çhanoi‘žr‰ffŽ‘žtfourŽ’‹z|²(Çhow‘­%‰ffŽ‘­'manyŽ‘0j—¸‘8àÇk–²,‘UUÇuseŽ‘#ã²,‘UUÇtoŽ‘ eز,‘UUÇfr‘ÿ}'omŽ‘)T²,‘UUÇwithoutŽ‘$9ç²,‘UUÇk“²);Ž¡‘R¸gŽ¡‘HgŽŸ €‘>¼De nes:ޤ €‘HÍassert¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍfrom¼,–ÕXnevÃŽer“used.Ž¡‘HÍhanoi_four¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍhow_many¼,–ÕXnevÃŽer“used.Ž¡‘HÍk¼,–ÕXnevÃŽer“used.Ž¡‘HÍto¼,–ÕXnevÃŽer“used.Ž¡‘HÍuse¼,–ÕXnevÃŽer“used.Ž¡‘HÍwithout¼,–ÕXnevÃŽer“used.Ž¡‘>Uses–ÕXÍhanoi_old“¼4a.ŽŽŸ’è²4ŽŽŒ‹Ý y ý£ ? ýä‘M²Hoš¸ãw–UUto“in˜v˜ok˜e...ŽŸ‘$˜¼5Ž‘>¸hÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iŽ’¾¸²+Ž’ÅäÖ¸ŽŽ¤ ‘HÆpublicŽ‘iÿõstaticŽ’ˆµ™v®9oidŽ’¡ <ÇmainŽ’·Þç²(ÆStringŽ‘î/²[‘ª®]‘UUÇar‘ÿ}'gsŽ‘¨Ù²)‘UU¸fŽ¡‘RÆifŽ‘\ ©²(Çar‘ÿ}'gsŽ‘S„µ:ÇlengthŽ‘[¸6²=‘Ç2)‘UU¸fŽ¡‘\ÇSystemŽ‘{oµ:ÇerrŽ‘µ:ÇprintlnŽ‘H›²(¹"Usage: Hanoi n k"Ž‘^ʲ);Ž¡‘\ÇSystemŽ‘{oµ:ÇexitŽ‘“‡²(1);Ž¡‘R¸gŽ¡‘RÆin®9tŽ‘cÃÇn‘‹{¸ ‘ÇÇInte‘ÿ}'gerŽ‘"(͵:Çp‘ÿ}'arseIntŽ‘$]r²(Çar‘ÿ}'gsŽ‘S„²[0]);Ž¡‘RÆin®9tŽ‘cÃÇk‘Ú¥¸ ‘ÇÇInte‘ÿ}'gerŽ‘"(͵:Çp‘ÿ}'arseIntŽ‘$]r²(Çar‘ÿ}'gsŽ‘S„²[1]);Ž¡‘RÇassertŽ‘l`P²(Çk‘Ú¥µ>‘Dz0);‘qÉ//–UUto“view“the“to•¸ãw“ers,›UUw“e'll˜use˜a˜¹Hanoi‘¡E‰ff&fŽ‘Ç«view˜²for˜4˜to“w“ersŽŽ¡‘RÇviewŽ‘hÃܸ ‘ÇÆnewŽ‘ƒÇHanoiViewŽŽ‘K=¿²(4,‘UUÇn‘Äc²);Ž¡‘RÇSystemŽ‘qoµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(¹"Starting to hanoi on four towers (n="ޒɏn²+–8àÇn‘ýC²+“¹" bricks, k="Ž‘H±™²+“Çk‘Lm²+“¹")"Ž‘ø×²);Ž¡‘RÇviewŽ‘eüĵ:ÇshowŽ‘%²(‘ª®);Ž¡‘RÇhanoi‘žr‰ffŽ‘žtfourŽ’z{²(Çn‘Äc²,–UU1,“4,“2,“3,“Çk‘²);Ž¡‘RÇSystemŽ‘qoµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(¹"Needed "Ž–1xŲ+‘8àÇmovesŽ‘׿²+‘8à¹" moves."Ž“²);Ž¡‘RÇSystemŽ‘qoµ:ÇerrŽ‘µ:ÇprintlnŽ‘H›²(¹"Needed "Ž–1xŲ+‘8àÇmovesŽ‘׿²+‘8à¹" moves!"Ž“²);Ž¡‘H¸gŽŸ €‘>¼De nes:ޤ €‘HÍInteger¼,–ÕXnevÃŽer“used.Ž¡‘HÍSystem¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍargs¼,–ÕXnevÃŽer“used.Ž¡‘HÍerr¼,–ÕXnevÃŽer“used.Ž¡‘HÍk¼,–ÕXnevÃŽer“used.Ž¡‘HÍlength¼,–ÕXnevÃŽer“used.Ž¡‘HÍmain¼,–ÕXnevÃŽer“used.Ž¡‘HÍn¼,–ÕXnevÃŽer“used.Ž¡‘HÍparseInt¼,–ÕXnevÃŽer“used.Ž¡‘HÍprintln¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘>Uses–âáÍHanoiView“¼2b“6,›æDÍassert“¼2a“4a“4b“6“8,˜Íexit¼,˜Íhanoi_four“¼4b,˜Ímoves“¼2b“3a,˜Íout¼,˜Íshow“¼9a,Ž¡‘Hand–ÕXÍview“¼2b“3a.ŽŽŸ’è²5ŽŽŒ‹ … y ý£ ? ýä‘>Å2Ž‘VLËAnimated‘ffHanoiŽŸç‘>²Here's–Åa“view“of“the“Hanoi“example.‘ÀÐIt's“a“class“that“can“bGe“used“to“visualizeޤ ‘>the›UUto•¸ãw“ers˜of˜Hanoi˜with˜up˜to˜n˜landing˜places˜for˜blic“ks.ŽŸ‘$˜¼6Ž‘>¸hÇHanoiView.java‘“ç¼6¸iŽ’’¦OŽ¡‘H²//–UUview“of“HanoiŽŽ¡‘HÆclassŽ‘bMHanoiViewŽ’ë¸fŽ¡‘RhÇView–“çclass“variables“¼7a¸iŽŽ¡‘UUVhÇView–“çclass“metho‘ÿ}'ds“¼7b¸iŽŽ¡‘UUVhÇView–“çmain“r‘ÿ}'outine“¼9b¸iŽŽ¡‘UUVÆstaticŽ‘t úv®9oidŽ’ŒuÇassert²(Æb•QÇo“oleanŽ‘*N*Çt²,‘UUÆStringŽ‘%˜ÙÇmessageŽ‘Ii²)‘UU¸fŽ¡‘\ÆifŽ‘f ª²(¸:ÇtŽ‘ ïÿ²)‘UU¸fŽ¡‘fÇSystemŽ’…oµ:ÇerrŽ‘µ:ÇprintlnŽ‘H›²(¹"Assertion violation: "Ž‘zø›²+‘8àÇmessageŽ‘&=p²);Ž¡‘fÇSystemŽ’…oµ:ÇexitŽ‘“‡²(1);Ž¡‘\¸gŽ¡‘RgŽ¡‘HgŽŸ €‘>¼De nes:ޤ €‘HÍHanoiView¼,–ÕXused“in“c•ÃŽh“unks–ÕX5“and“7b.Ž¡‘HÍSystem¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍassert¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍerr¼,–ÕXnevÃŽer“used.Ž¡‘HÍmessage¼,–ÕXnevÃŽer“used.Ž¡‘HÍprintln¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍt¼,–ÕXused“in“c•ÃŽh“unk‘ÕX9a.Ž¡‘>Uses‘ÕXÍexit¼.ŽŸ þ6‘>ó#ÂÖN  cmbx12Î2.1Ž‘\ÀUsingŽŸuT‘>²Hoš¸ãw–´$to“use“this“view?‘Ž5Just“create“a“Hanoi“view“with“¹new“²and“tell“it,‘ Øho˜wޤ ‘>man•¸ãy›k›to“w“ers˜y“ou˜ha“v“e˜and˜ho“w˜man“y˜bric“ks˜y“ou˜w“an“t˜to˜manipulate˜(e.g.‘´™¹newŽ¡‘>HanoiView(4,6)–þê²for“four“to•¸ãw“ers–þêand“6“bric¸ãks).‘ n†Then“simply“call“the“¹moveŽ¡‘>²methoGd–œon“this“view“and“tell“it,‘Þ.to“mo•¸ãv“e–œa“bric¸ãk“from“where“to“where“(e.g.Ž¡‘>¹move(1,4)–&вto“mo•¸ãv“e–&Ða“bricš¸ãk“from“to˜w˜er“1“to“to˜w˜er“4,‘0if“there“are“so“man˜y).‘bETheŽ¡‘>class–£will“c•¸ãhec“k–£the“argumenš¸ãts“of“¹move“²but“w˜on't“c˜hec˜k,‘Ʋif“y˜ou're“putting“a“largerŽ¡‘>bricš¸ãk–íÑon“a“smaller“bric˜k.‘;are–UUno“accessor“functions“to“the“to•¸ãw“ers‘UUy“et.ŽŽŸ’è6ŽŽŒ‹'÷ y ý£ ? ýä‘>Î2.2Ž‘\ÀImplemen tationŽŸuT‘>²The–™Tidea“of“this“view“is“to“ha•¸ãv“e›™Tt“w“o˜¹int˜²arra“ys˜that˜k“eep˜trac“k˜of˜whic“h˜bric“kޤ ‘>is–Uwhere.‘ÌÆBricš¸ãks“are“denoted“b˜y“in˜tegers“bGet˜w˜een“1“and“the“n˜um˜bGer“giv˜en“inŽ¡‘>the–Pconstructor.‘bThe“ rst“arraš¸ãy“¹turm“²is“a“t˜w˜o-dimensional“arra˜y‘ÿ*ª.‘bThe“v‘ÿqÇalueŽ¡‘>of–‰¤¹turm[i]“²stores“the“actual“status“of“to•¸ãw“er–‰¤¹i²,›–¸i.e.‘µ¹turm[i][j]“²tells“us,˜whic¸ãhŽ¡‘>bricš¸ãk–D¡is“at“lev˜el“¹j“²in“to˜w˜er“¹i².‘l6The“lev˜els“coun˜t“from“0“to“the“maxim˜um“n˜um˜bGerŽ¡‘>of–UUbricš¸ãks“giv˜en“in“the“constructor.Ž¡‘MThere's–Ä…an“additional“arraš¸ãy“¹hoehe“²that“is“implicitly“con˜tained“in“¹turm“²butŽ¡‘>is–ƒkš¸ãept“for“easy“access.‘ûThe“v‘ÿqÇalue“of“¹hoehe[i]“²coun˜ts“the“n˜um˜bGer“of“bric˜ks“onŽ¡‘>to•¸ãw“er‘UU¹i².ŽŸB«‘Ñ”¼7aŽ‘>¸hÇView–“çclass“variables“¼7a¸iŽ’©&GŽ¡‘HÆin®9tŽ‘YÂÇt‘¹ð¸ ‘Dz0;‘qÉ//›UUn•¸ãum“bGer˜of˜to“w“ersŽŽ¡‘HÆin®9tŽ‘YÂÇn‘‹{¸ ‘Dz0;‘qÉ//›UUn•¸ãum“bGer˜of˜bric“ksŽŽ¡‘HÆin®9tŽ‘YÂÇturmŽ‘nëq²[–ª®][“];‘qÉ//–UUnew“in¸ãt“[t][n];ŽŽ¡‘HÆin®9tŽ‘YÂÇho‘ÿ}'eheŽ‘qײ[‘ª®];‘qÉ//–UUnew“in¸ãt“[t];ŽŽ¡© ¡U‘>¼De nes:ޤ €‘HÍhoehe¼,–ÕXused“in“c•ÃŽh“unks–ÕX7b“and“8.Ž¡‘HÍn¼,–ÕXnevÃŽer“used.Ž¡‘HÍt¼,–ÕXused“in“c•ÃŽh“unk‘ÕX9a.Ž¡‘HÍturm¼,–ÕXused“in“c•ÃŽh“unks‘ÕX7{9.ŽŸ…V‘X°7bŽ‘>¸hÇView–“çclass“metho‘ÿ}'ds“¼7b¸iŽ’¦®Òޤ ‘HÆHanoiViewŽ‘Œ^²(Æin®9tŽ‘ÂÇtowersŽ‘-ß’²,‘UUÆin®9tŽ‘gÇbricksŽ‘.eB²)‘UU¸fŽ¡‘RÇt‘¹ð¸ ‘ÇÇtowersŽ‘”è²;Ž¡‘RÇn‘‹{¸ ‘ÇÇbricksŽ‘ÅC²;Ž¡‘RÇturmŽ‘j È¸ ‘ÇÆnewŽ‘ƒin®9tŽŽ‘'Ïð²[Çt‘òز][Çn‘Äc²];Ž¡‘RÇho‘ÿ}'eheŽ‘m¸ ‘ÇÆnewŽ‘ƒin®9tŽŽ‘'Ïð²[Çt‘òز];‘qÉ//–UUinitialize“ev¸ãerythingŽŽ¡‘RÆforŽ‘cUR²(Æin®9tŽ‘ÂÇi–Ëò¸ ›Ç²0;‘qÇÇi“µ<˜Çt‘òز;‘qÇÇi‘Ú¹++ŽŽ‘«²)‘UU¸fŽ¡‘\Çho‘ÿ}'eheŽ‘tƲ[Çi‘Ú²]–Ǹ “²0;Ž¡‘\ÆforŽ‘mUS²(Æin®9tŽ‘ÂÇj–9u¸ ›Ç²0;‘qÇÇj“µ<˜Çn‘Äc²;‘qÇÇj‘r]¹++ŽŽ‘u.²)‘UU¸fŽ¡‘fÇturmŽ‘{Ù²²[Çi‘Ú²][Çj‘r]²]–Ǹ “²0;Ž¡‘\¸gŽ¡‘Rg‘²//–UUn“bricš¸ãks“are“on“ rst“to˜w˜er“(should“this“bGe“part“of“theŽŽ¡‘k//‘UUconstructor??)ŽŽ¡‘RÇho‘ÿ}'eheŽ‘jƲ[0]–Ǹ “Çn‘Äc²;Ž¡‘RÆforŽ‘cUR²(Æin®9tŽ‘ÂÇi–Ëò¸ ›Ç²0;‘qÇÇi“µ<˜Çn‘Äc²;‘qÇÇi‘Ú¹++ŽŽ‘«²)‘UU¸fŽ¡‘\ÇturmŽ‘qÙ±²[0][Çn‘ýC¸–8à²1“¸“Çi‘Ú²]–Ǹ “Çi‘=º²+‘8à1;Ž¡‘R¸gŽ¡‘Hgަ‘>¼De nes:ޤ €‘HÍbricks¼,–ÕXnevÃŽer“used.Ž¡‘HÍi¼,–ÕXnevÃŽer“used.Ž¡‘HÍj¼,–ÕXnevÃŽer“used.Ž¡‘HÍn¼,–ÕXnevÃŽer“used.Ž¡‘HÍt¼,–ÕXused“in“c•ÃŽh“unk‘ÕX9a.Ž¡‘HÍtowers¼,–ÕXnevÃŽer“used.Ž¡‘>Uses–ÕXÍHanoiView“¼2b“6,“Íhoehe“¼7a,“and“Íturm“¼7a.ŽŽŸ’è²7ŽŽŒ‹/Ý y ý£ ? ýä‘M²Noš¸ãw–UUfor“the“mo˜v˜es.‘qÇThe“heigh˜t“of“¹to“²is“incremen˜ted.ŽŸ‘$˜¼8Ž‘>¸hÇView–“çclass“metho‘ÿ}'ds“¼7b¸iŽ’¦®Ò²+Ž’®u𸎎¤ ‘HÆv®9oidŽ‘`j£ÇmoveŽ‘w¨²(Æin®9tŽ‘ÂÇfr‘ÿ}'omŽ‘%åÁ²,‘UUÆin®9tŽ‘gÇtoŽ‘wš²)‘UU¸fŽ¡‘RÇassertŽ‘l`P²(1–Ǹ“Çfr‘ÿ}'omŽ–Ó÷¸^‘8àÇfr‘ÿ}'omŽ“¸‘ÇÇt‘òز,‘UU¹"Illegale Turm-Nummer "Ž‘~Mð²+‘8àÇfr‘ÿ}'omŽ‘ ß²);Ž¡‘RÇassertŽ‘l`P²(1–Ǹ“ÇtoŽ–{¸^‘8àÇtoŽ“¸‘ÇÇt‘òز,‘UU¹"Illegale Turm-Nummer "Ž‘~Mð²+‘8àÇtoŽ‘ Ic²);Ž¡‘RÇassertŽ‘l`P²(Çho‘ÿ}'eheŽ‘Ʋ[Çfr‘ÿ}'omŽ‘ ߸›8à²1]–ǵ>“²0,‘UU¹"keine Scheiben mehr auf Turm "Ž’¨Mز+˜Çfr‘ÿ}'omŽ‘ ß²);Ž¡‘RÇho‘ÿ}'eheŽ‘jƲ[ÇtoŽ› Ic¸‘8à²1]–Ǹ “Çho‘ÿ}'eheŽ‘²[ÇtoŽ˜¸–8à²1]“+“1;Ž¡‘RÇturmŽ‘gÙ°²[ÇtoŽ– Ic¸›8à²1][Çho‘ÿ}'eheŽ‘Ʋ[ÇtoŽ“¸˜²1]˜¸˜²1]–Ǹ “ÇturmŽ‘ Ç²[Çfr‘ÿ}'omŽ– ߸˜²1][Çho‘ÿ}'eheŽ‘Ʋ[Çfr‘ÿ}'omŽ“¸˜²1]˜¸˜²1];Ž¡‘RÇturmŽ‘gÙ°²[Çfr‘ÿ}'omŽ– ߸›8à²1][Çho‘ÿ}'eheŽ‘Ʋ[Çfr‘ÿ}'omŽ“¸˜²1]˜¸˜²1]–Ǹ “²0;Ž¡‘RÇho‘ÿ}'eheŽ‘jƲ[Çfr‘ÿ}'omŽ› ߸‘8à²1]–Ǹ “Çho‘ÿ}'eheŽ‘²[Çfr‘ÿ}'omŽ˜¸–8à²1]“¸“²1;Ž¡‘RÇshowŽ‘h&²(‘ª®);Ž¡‘RÆtryŽ‘dœn¸fŽ¡‘\Æin®9tŽ‘mÄÇs‘™9¸ ‘ÇÇSystemŽ‘"6µ:ÇinŽ‘ t»µ:Çr–ÿ}'e“adŽ‘ ò(‘ª®);Ž¡‘R¸g‘UUÆcatc®9hŽ‘¯õ²(ÇjavaŽ‘§êµ:ÇioŽ‘Ïµ:ÇIOExc‘ÿ}'eptionŽ‘9÷e1Ž‘EŒ²)‘UU¸fŽ¡‘RgŽ¡‘HgŽŸ €‘>¼De nes:ޤ €‘HÍSystem¼,–ÕXused“in“c•ÃŽh“unks–ÕX3a“and“9a.Ž¡‘HÍassert¼,–ÕXused“in“c•ÃŽh“unk‘ÕX5.Ž¡‘HÍfrom¼,–ÕXnevÃŽer“used.Ž¡‘HÍin¼,–ÕXnevÃŽer“used.Ž¡‘HÍmove¼,–ÕXused“in“c•ÃŽh“unk‘ÕX4a.Ž¡‘HÍread¼,–ÕXnevÃŽer“used.Ž¡‘HÍs¼,–ÕXnevÃŽer“used.Ž¡‘HÍt¼,–ÕXused“in“c•ÃŽh“unk‘ÕX9a.Ž¡‘HÍto¼,–ÕXnevÃŽer“used.Ž¡‘>Uses–ÕXÍIOException¼,“Íe1¼,“Íhoehe“¼7a,“Íio¼,“Íjava¼,“Íshow“¼9a,“and“Íturm“¼7a.ŽŽŸ’è²8ŽŽŒ‹ : y ý£ ? ýä‘M²Bricš¸ãks–t4are“visualized“as“a“series“of“2–Mt¸“µn–t4²c˜haracters“in“a“ro˜w.‘ÎcThe“maxim˜umޤ ‘>width–ª™of“a“to•¸ãw“er–ª™is“therefore“2–q·¸“µn²,‘¿éand–ª™for“evš¸ãery“bric˜k“µb²,‘¿éw˜e“ rst“output“µn–q·¸“µbŽ¡‘>²spaces,‘6éthen›/N2–ìÒ¸“µb˜²c¸ãharacters,‘6éand˜then˜again˜µn“¸“µb˜²spaces,‘6éwhic•¸ãh˜giv“es˜a˜total˜ofŽ¡‘>µn–8ณµb“²+“2“¸“µb“²+“µn“¸“µb–Dz=“2–8ณµn‘UU²c¸ãharacters.ŽŸ‘Ñ”¼9aŽ‘>¸hÇView–“çclass“metho‘ÿ}'ds“¼7b¸iŽ’¦®Ò²+Ž’®u𸎎¡‘HÆv®9oidŽ‘`j£ÇshowŽ‘vrȲ(‘ª®)‘UU¸fŽ¡‘RÆforŽ‘cUR²(Æin®9tŽ‘ÂÇj–9u¸ ›ÇÇn‘ýC¸‘8à²1;‘qÇÇj“¸˜²0;‘qÇÇj‘r]¹--ŽŽ‘u.²)–UU¸f‘²//“for“evš¸ãery“pGossible“bric˜kŽŽ¡‘k//–UU(instead“of“n-1“could“takš¸ãe“max(hoGehe[i])“for“ev˜ery“i)ŽŽ¡‘\ÆforŽ‘mUS²(Æin®9tŽ‘ÂÇi–Ëò¸ ›Ç²0;‘qÇÇi“µ<˜Çt‘òز;‘qÇÇi‘Ú¹++ŽŽ‘«²)–UU¸f‘²//“for“evš¸ãery“to˜w˜erŽŽ¡‘u//–UUturm[i][j]“is“n•¸ãum“bGer–UUof“bric¸ãkŽŽ¡‘u//–UUoutput“n-b“spacesŽŽ¡‘fÆforŽ‘wUT²(Æin®9tŽ‘ÂÇk–Ú¥¸ ›Ç²0;‘qÇÇk“µ<˜Çn‘ýC¸‘8àÇturmŽ‘²[Çi‘Ú²][Çj‘r]²];‘qÇÇk‘¹++ŽŽ‘žå²)‘UU¸fŽ¡‘pÇSystemŽ’oµ:ÇoutŽ‘¿Ÿµ:ÇprintŽ‘I²(¹" "Ž‘¿÷²);Ž¡‘f¸g‘²//–UUoutput“2*b“lettersŽŽ¡‘fÆforŽ‘wUT²(Æin®9tŽ‘ÂÇk–Ú¥¸ ›Ç²0;‘qÇÇk“µ<˜²2–8ณÇturmŽ‘²[Çi‘Ú²][Çj‘r]²];‘qÇÇk‘¹++ŽŽ‘žå²)–UU¸f‘²//“NB“radix“is“n+1,“i.e.‘qÇ10=A“etc.ŽŽ¡‘pÇSystemŽ’oµ:ÇoutŽ‘¿Ÿµ:ÇprintŽ‘I²(ÇChar‘ÿ}'acterŽ‘,fµ:ÇforDigitŽ‘"òȲ(ÇturmŽ‘Ù¯²[Çi‘Ú²][Çj‘r]²],‘UUÇn‘ýC²+‘8à1));Ž¡‘f¸gŽ¡‘fÆforŽ‘wUT²(Æin®9tŽ‘ÂÇk–Ú¥¸ ›Ç²0;‘qÇÇk“µ<˜Çn‘ýC¸‘8àÇturmŽ‘²[Çi‘Ú²][Çj‘r]²];‘qÇÇk‘¹++ŽŽ‘žå²)‘UU¸fŽ¡‘pÇSystemŽ’oµ:ÇoutŽ‘¿Ÿµ:ÇprintŽ‘I²(¹" "Ž‘¿÷²);Ž¡‘f¸gŽ¡‘\gŽ¡‘\ÇSystemŽ‘{oµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(‘ª®);Ž¡‘R¸gŽ¡‘RÆforŽ‘cUR²(Æin®9tŽ‘ÂÇi–Ëò¸ ›Ç²0;‘qÇÇi“µ<˜Çt‘òز;‘qÇÇi‘Ú¹++ŽŽ‘«²)‘UU¸fŽ¡‘\ÆforŽ‘mUS²(Æin®9tŽ‘ÂÇj–9u¸ ›Ç²0;‘qÇÇj“µ<˜Çn‘Äc²;‘qÇÇj‘r]¹++ŽŽ‘u.²)‘UU¸fŽ¡‘fÇSystemŽ’…oµ:ÇoutŽ‘¿Ÿµ:ÇprintŽ‘I²(¹"--"Ž‘ÿô²);Ž¡‘\¸gŽ¡‘RgŽ¡‘RÇSystemŽ‘qoµ:ÇoutŽ‘¿Ÿµ:ÇprintlnŽ‘H›²(‘ª®);Ž¡‘H¸gŽŸ €‘>¼De nes:ޤ €‘HÍi¼,–ÕXnevÃŽer“used.Ž¡‘HÍj¼,–ÕXnevÃŽer“used.Ž¡‘HÍk¼,–ÕXnevÃŽer“used.Ž¡‘HÍn¼,–ÕXnevÃŽer“used.Ž¡‘HÍshow¼,–ÕXused“in“c•ÃŽh“unks–ÕX5“and“8.Ž¡‘>Uses–ïÍCharacter¼,›PÕÍSystem“¼2a“5“6“8,˜ÍforDigit¼,˜Íout¼,˜Íprint¼,˜Íprintln“¼2a“5“6,Ž¡‘HÍt–ÕX¼2a“2a“6“6“7a“7b“7b“7b“8,“and“Íturm“¼7a.ŽŸ‘X°9bŽ‘>¸hÇView–“çmain“r‘ÿ}'outine“¼9b¸iŽ’£ÿ䎎Ÿ’è²9ŽŽŒ‹ AÀ y ý£ ? ýä‘>Å3Ž‘VLËList–ffof“Re nemenŒÌtsŽŸç‘>¸hÇF‘ÿ;¼unctions–“çof“Hanoi“class“¼3a¸iޤ ‘>hÇHanoi–“çclass“variables“¼2b¸iŽ¡‘>hÇHanoiView.java‘“ç¼6¸iŽ¡‘>hÇHanoi.java‘“ç¼2a¸iŽ¡‘>hÇView–“çclass“metho‘ÿ}'ds“¼7b¸iŽ¡‘>hÇView–“çclass“variables“¼7a¸iŽ¡‘>hÇView–“çmain“r‘ÿ}'outine“¼9b¸iŽŸ!Ä‘>Å4Ž‘VLËIndexŽŸç‘>¹Character²:‘ãŽ9aŽ¡‘>¹Hanoi²:‘ãŽ2aŽ‘㎟™”‰fe ŽŽ¡‘>¹HanoiView²:‘ãŽ2bŽ‘㎟™”‰fe Ž;Ž‘qÉ,–UU5,“6Ž“Ÿ™”‰feŽ‘UV,“7bŽ¡‘>¹IOException²:‘ãŽ8Ž¡‘>¹Integer²:‘ãŽ5Ž‘㎟™”‰feŽ‘ ã,‘UU5Ž‘UUŸ™”‰feŽŽ¡‘>¹System²:‘ãŽ2aŽ‘㎟™”‰fe Ž‘ã,–UU3a,“5Ž“Ÿ™”‰feŽ›UV,“6Ž“Ÿ™”‰feŽ˜,“8Ž“Ÿ™”‰feŽ˜,“9aŽ¡‘>¹args²:‘ãŽ5Ž‘㎟™”‰feŽ‘ ã,‘UU5Ž‘UUŸ™”‰feŽ–UV,‘UU5Ž‘UUŸ™”‰feŽ“,‘UU5Ž‘UUŸ™”‰feŽŽ¡‘>¹assert²:‘ãŽ2aŽ‘㎟™”‰fe Ž‘ã,‘UU4aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž‘ ã,–UU5,“6Ž“Ÿ™”‰feŽ‘UV,“8Ž“Ÿ™”‰feŽŽ¡‘>¹boring_size²:‘ãŽ3a,‘UU3bŽ‘UUŸ™”‰fe Ž;ŽŽ¡‘>¹boring_size_slice²:‘ãŽ3a,‘UU3bŽ‘UUŸ™”‰fe Ž;ŽŽ¡‘>¹bricks²:‘ãŽ7bŽ‘㎟™”‰fe Ž;ŽŽ¡‘>¹e1²:‘ãŽ8Ž¡‘>¹err²:‘ãŽ2aŽ‘㎟™”‰fe Ž‘ã,‘UU5Ž‘UUŸ™”‰feŽ‘UV,‘UU6Ž‘UUŸ™”‰feŽŽ¡‘>¹exit²:‘ãŽ2a,–UU5,“6Ž¡‘>¹forDigit²:‘ãŽ9aŽ¡‘>¹from²:‘ãŽ3aŽ‘㎟™”‰fe Ž‘ã,‘UU3aŽ‘UUŸ™”‰fe Ž– UW,‘UU4aŽ‘UUŸ™”‰fe Ž“,‘UU4aŽ‘UUŸ™”‰fe Ž“,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž– ã,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž“,‘UU8Ž‘UUŸ™”‰feŽ–UV,‘UU8Ž‘UUŸ™”‰feŽ“,‘UU8Ž‘UUŸ™”‰feŽ“,‘UU8Ž‘UUŸ™”‰feŽŽ¡‘>¹hanoi_four²:‘ãŽ4bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU5Ž¡‘>¹hanoi_old²:‘ãŽ4aŽ‘㎟™”‰fe Ž‘ã,‘UU4bŽ¡‘>¹hoehe²:‘ãŽ7aŽ‘㎟™”‰fe Ž‘ã,–UU7b,“8Ž¡‘>¹how_many²:‘ãŽ4aŽ‘㎟™”‰fe Ž‘ã,‘UU4bŽ‘UUŸ™”‰fe Ž;ŽŽ¡‘>¹i²:‘ãŽ7bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU7bŽ‘UUŸ™”‰fe Ž;Ž‘ ã,‘UU9aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU9aŽ‘UUŸ™”‰fe ŽŽ¡‘>¹in²:‘ãŽ8Ž‘㎟™”‰feŽŽ¡‘>¹io²:‘ãŽ8Ž¡‘>¹j²:‘ãŽ7bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU9aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU9aŽ‘UUŸ™”‰fe ŽŽ¡‘>¹java²:‘ãŽ8Ž¡‘>¹k²:‘ãŽ4bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU5Ž‘UUŸ™”‰feŽ‘UV,‘UU9aŽ‘UUŸ™”‰fe Ž– UW,‘UU9aŽ‘UUŸ™”‰fe Ž“,‘UU9aŽ‘UUŸ™”‰fe ŽŽ¡‘>¹length²:‘ãŽ5Ž‘㎟™”‰feŽŽ¡‘>¹main²:‘ãŽ5Ž‘㎟™”‰feŽŽ¡‘>¹message²:‘ãŽ6Ž‘㎟™”‰feŽ‘ ã,‘UU6Ž‘UUŸ™”‰feŽŽ¡‘>¹move²:‘ãŽ3aŽ‘㎟™”‰fe Ž‘ã,‘UU3aŽ‘UUŸ™”‰fe Ž‘ UW,–UU4a,“8Ž“Ÿ™”‰feŽŽ¡‘>¹moves²:‘ãŽ2bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU3aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU5Ž¡‘>¹n²:‘ãŽ5Ž‘㎟™”‰feŽ‘ ã,‘UU7aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU7bŽ‘UUŸ™”‰fe Ž;Ž‘ ã,‘UU9aŽ‘UUŸ™”‰fe ŽŽ¡‘>¹out²:‘ãŽ3a,–UU5,“9aŽŽŸ’åÿ10ŽŽŒ‹ Kí y ý£ ? ýä‘>¹parseInt²:‘ãŽ5Ž‘㎟™”‰feŽ‘ ã,‘UU5Ž‘UUŸ™”‰feŽŽ¤ ‘>¹print²:‘ãŽ9aŽ¡‘>¹println²:‘ãŽ2aŽ‘㎟™”‰fe Ž‘ã,–UU3a,“5Ž“Ÿ™”‰feŽ›UV,“6Ž“Ÿ™”‰feŽ˜,“9aŽ¡‘>¹read²:‘ãŽ8Ž‘㎟™”‰feŽŽ¡‘>¹s²:‘ãŽ8Ž‘㎟™”‰feŽŽ¡‘>¹show²:‘ãŽ5,–UU8,“9aŽ“Ÿ™”‰fe ŽŽ¡‘>¹t²:‘ãŽ2aŽ‘㎟™”‰fe Ž‘ã,‘UU2aŽ‘UUŸ™”‰fe Ž› UW,‘UU6Ž‘UUŸ™”‰feŽ–UV,‘UU6Ž‘UUŸ™”‰feŽ“,‘UU7aŽ‘UUŸ™”‰fe Ž˜,‘UU7bŽ‘UUŸ™”‰fe Ž;Ž– ã,‘UU7bŽ‘UUŸ™”‰fe Ž;Ž“,‘UU7bŽ‘UUŸ™”‰fe Ž;Ž“,‘UU8Ž‘UUŸ™”‰feŽ‘UV,‘UU9aŽ¡‘>¹to²:‘ãŽ3aŽ‘㎟™”‰fe Ž‘ã,‘UU3aŽ‘UUŸ™”‰fe Ž– UW,‘UU4aŽ‘UUŸ™”‰fe Ž“,‘UU4aŽ‘UUŸ™”‰fe Ž“,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž– ã,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž“,‘UU8Ž‘UUŸ™”‰feŽŽ¡‘>¹towers²:‘ãŽ7bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU7bŽ‘UUŸ™”‰fe Ž;ŽŽ¡‘>¹turm²:‘ãŽ7aŽ‘㎟™”‰fe Ž‘ã,–UU7b,“8,“9aŽ¡‘>¹use²:‘ãŽ4aŽ‘㎟™”‰fe Ž‘ã,‘UU4aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž‘ ã,‘UU4bŽ‘UUŸ™”‰fe Ž;ŽŽ¡‘>¹view²:‘ãŽ2bŽ‘㎟™”‰fe Ž;Ž‘qÉ,‘UU3aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU5Ž¡‘>¹without²:‘ãŽ4aŽ‘㎟™”‰fe Ž‘ã,‘UU4aŽ‘UUŸ™”‰fe Ž‘ UW,‘UU4bŽ‘UUŸ™”‰fe Ž;Ž‘ ã,‘UU4bŽ‘UUŸ™”‰fe Ž;ŽŽŽŸ’åÿ11ŽŽŒøWwƒ’À;èy— ó#ÂÖN  cmbx12ó"ßCÊscmtt8óý': cmti10óò"V cmbx10óÂÖN ff cmbx12ó|{Ycmr8óX«Q cmr12óDÓítG®G®cmr17óßê cmmi10óKñ`y cmr10ù\þßßßßßpretzel-2.0n-2/contrib/noweb/java.latex/Hanoi.nw0000644000000000000000000001665506520323243020302 0ustar rootroot\documentclass{article} \usepackage{noweb} \usepackage{pretzel-noweb} % % A small Java example for use with noweb % \begin{document} \title{Towers of Hanoi revisited} \author{Felix G\"artner} \maketitle \tableofcontents \section{Introduction} A ``towers of hanoi'' implementation with four landing places for bricks. This file was written using the {\tt noweb} literate programming system. To get a Java file from this text, run {\tt notangle} on it. @ Here's the frame of it all. All stuff is included within the [[Hanoi]] class, i.e. also the auxiliary functions like [[assert]]. <>= // towers of hanoi with four boxes class Hanoi { <> <> //@cancel static void assert(boolean t) { if (!t) { System.err.println("Assertion violation"); System.exit(1); } } } @ The moves that have been taken by this algorithm are counted in [[moves]]. Also, we can use a [[HanoiView]] object to have a look at what's going on. <>= static int moves = 0; static HanoiView view = null; @ All stuff will be broken down to calls of this function. It is an interface to possible visualization tools. We'll count the moves here. <>= static void move( int from, int to ) { moves++; if (moves > boring_size) { // only output sporadic progress reports if (moves % boring_size_slice == 0) { System.out.println("Finished " + moves + ". move..."); } } else { System.out.println("Moving from " + from + " to " + to + "... (" + moves + ". move)"); if (view != null) view.move(from, to); } } @ <>= static final int boring_size = 100; static final int boring_size_slice = 100; @ Here's the old ``straight out of the hat'' implementation of the towers using only three boxes. It won't use the [[without]] box. <>= static void hanoi_old( int how_many, int from, int to, int use, int without ) { assert( from + to + use + without == 10 ); if (how_many == 1) { move( from, to ); } else { hanoi_old( how_many-1, from, use, to, without ); move( from, to ); hanoi_old( how_many-1, use, to, from, without ); } } @ The idea behind this four box implementation is to move slices of $k$ bricks at a time. The fourth box is used to enable building these $k$-brick bricks. <>= static void hanoi_four( int how_many, int from, int to, int use, int without, int k ) { assert( from + to + use + without == 10 ); if (how_many <= k) { hanoi_old( how_many, from, to, without, use ); } else { hanoi_four( how_many-k, from, use, to, without, k ); hanoi_old( k, from, to, without, use ); hanoi_four( how_many-k, use, to, from, without, k ); } } @ How to invoke... <>= public static void main (String[] args) { if (args.length != 2) { System.err.println("Usage: Hanoi n k"); System.exit(1); } int n = Integer.parseInt(args[0]); int k = Integer.parseInt(args[1]); assert(k>0); // to view the towers, we'll use a \texttt{Hanoi\_view} for 4 towers view = new HanoiView(4,n); System.out.println("Starting to hanoi on four towers (n=" + n + " bricks, k=" + k + ")"); view.show(); hanoi_four( n, 1, 4, 2, 3, k ); System.out.println("Needed " + moves + " moves."); System.err.println("Needed " + moves + " moves!"); } @ \section{Animated Hanoi} Here's a view of the Hanoi example. It's a class that can be used to visualize the towers of Hanoi with up to n landing places for blicks. <>= // view of Hanoi class HanoiView { <> <> <> static void assert(boolean t, String message) { if (!t) { System.err.println("Assertion violation: " + message); System.exit(1); } } } @ \subsection{Using} How to use this view? Just create a Hanoi view with [[new]] and tell it, how many towers you have and how many bricks you want to manipulate (e.g. [[new HanoiView(4,6)]] for four towers and 6 bricks). Then simply call the [[move]] method on this view and tell it, to move a brick from where to where (e.g. [[move(1,4)]] to move a brick from tower 1 to tower 4, if there are so many). The class will check the arguments of [[move]] but won't check, if you're putting a larger brick on a smaller brick. You'll have to take care of this yourself. Also there are no accessor functions to the towers yet. @ \subsection{Implementation} The idea of this view is to have two [[int]] arrays that keep track of which brick is where. Bricks are denoted by integers between 1 and the number given in the constructor. The first array [[turm]] is a two-dimensional array. The value of [[turm[i]]] stores the actual status of tower [[i]], i.e. [[turm[i][j]]] tells us, which brick is at level [[j]] in tower [[i]]. The levels count from 0 to the maximum number of bricks given in the constructor. There's an additional array [[hoehe]] that is implicitly contained in [[turm]] but is kept for easy access. The value of [[hoehe[i]]] counts the number of bricks on tower [[i]]. <>= int t = 0; // number of towers int n = 0; // number of bricks int turm[][]; // new int [t][n]; int hoehe[]; // new int [t]; @ <>= HanoiView(int towers, int bricks) { t = towers; n = bricks; turm = new int[t][n]; hoehe = new int[t]; // initialize everything for (int i=0; i>= void move(int from, int to) { assert( 1<=from && from<=t, "Illegale Turm-Nummer " + from ); assert( 1<=to && to<=t, "Illegale Turm-Nummer " + to ); assert( hoehe[from-1] > 0 , "keine Scheiben mehr auf Turm " + from); hoehe[to-1] = hoehe[to-1] + 1; turm[to-1][hoehe[to-1]-1] = turm[from-1][hoehe[from-1]-1]; turm[from-1][hoehe[from-1]-1] = 0; hoehe[from-1] = hoehe[from-1] - 1; show(); try { int s = System.in.read(); } catch (java.io.IOException e1) { } } @ Bricks are visualized as a series of $2\cdot n$ characters in a row. The maximum width of a tower is therefore $2\cdot n$, and for every brick $b$, we first output $n-b$ spaces, then $2\cdot b$ characters, and then again $n-b$ spaces, which gives a total of $n-b+2\cdot b+n-b = 2\cdot n$ characters. <>= void show() { for (int j=n-1; j>=0; j--) { // for every possible brick // (instead of n-1 could take max(hoehe[i]) for every i) for (int i=0; i>= @ \section{List of Refinements} \nowebchunks \section{Index} \nowebindex \end{document} pretzel-2.0n-2/contrib/noweb/java.latex/javafx.fg0000644000000000000000000004142106537734432020476 0ustar rootroot/* * javafx.fg -- experimental Pretzel grammar for Java * * based on original version by Lee Wittenberg and enhanced * for use with noweb and made into a self contained * Pretzel file by Felix Gaertner * * History at end * * $Header: /a/spelunke/export/vol1/gaertner/pretzel/contrib/noweb/java.latex/RCS/javafx.fg,v 1.1 1997/07/09 14:24:27 gaertner Exp $ * */ /* * A word concerning indexing: I couldn't get noweb to typset identifiers * in different fonts in the index. Help on this is very welcome. The * current strategy leaves identifiers unchanged up to the very moment * their final look is determined (i.e. they change from ID_LIKE to * id_like). In this moment, we think about TeX and escape underlines. */ %token BINOP %token BREAK_LIKE %token CASE_LIKE %token CATCH_LIKE %token CHUNK %token CLASS %token COLON %token COMMA %token COMMENT %token DEFAULT_LIKE %token DOT %token DOT_STAR %token DO_LIKE %token ELSE_LIKE %token EXTENDS_LIKE %token FINALLY_LIKE %token FOR_LIKE %token ID_LIKE %token IF_LIKE %token IGNORE %token IMPORT_LIKE %token INCROP %token INT_LIKE %token LBRACE %token LBRACK %token LPAR %token NUM %token QUESTION %token RBRACE %token RBRACK %token RPAR %token SHORT_ID %token SEMI %token STRING %token SYNC_LIKE %token TRY_LIKE %token UNOP %token UNORBINOP %{ #include #include #include #include // for escaped_underlines /* flag to help distinguish betweet declaration and use of an identifier. * It's set to 1 whenever we think we're parsing a declaration. */ static int in_decl = 0; /* forward declarations: */ /* these functions help to typeset classes. They implement * a simple lookup table to see if an identifier is a * class or what... * * taken from Kernighan/Ritchie: The C Programming Language, p.144ff */ struct nlist { /* a table entry: */ struct nlist *next; /* next entry in chain */ char* name; /* the identifier */ }; /* size of hash table. Should be changed if you are working on large * programs. */ #define HASHSIZE 101 static struct nlist* hashtab[HASHSIZE]; /* the hash table */ /* form the hash value of a string */ static unsigned hash(char* s); /* lookup: look for s in hashtab * * returns a pointer to the found element or NULL if it was not * found. */ static struct nlist* lookup(char* s); /* install: put name in hashtab. * * returns a pointer to the new element if all went well, * returns NULL on error. */ static struct nlist *install(char* name); /* attibute_to_string - * turn an attribute into a string * */ static char* attribute_to_string( Attribute* a ); // forward declaration of a function that replaces `_' // with `\_' in a copy of s static char* escaped_underlines(char* s); /* debugging function */ static void debug_print( char* this_is, Attribute* stuff ); %} %% final : exp { "\\mathin " $1 "\\mathout" } | decl_list | IGNORE | COMMENT { "\\qquad" break_space $1 force } | IGNORE final | COMMENT final { $1 force $2 } ; decl_list : decl | decl_list decl { $1 force $2 } ; decl : exp block { "\\mathin" $1 "\\mathout\\ " $2 } ; block : lbrace rbrace { $1 force $2 } | lbrace decl_list rbrace { $1 cancel indent force $2 outdent force $3 } ; exp : expr | exp dot expr | exp comma expr { $1 $2 opt3 "\\mathin " $3 } | exp expr { $1 $2 } ; expr : term | expr binop term { $1 opt9 $2 $3 } | expr unorbinop term { $1 opt9 $2 $3 } | expr extends_like idlist { $1 "\\ " opt2 $2 "\\ " $3 } | expr brack_exp ; binop : question exp colon { "\\mathbin{" $1 $2 $3 "}" } ; idlist : ident | idlist comma ident { $1 $2 opt9 $3 } ; // Identifiers come as plain strings from the scanner. // Identifiers that are class names are installed into the lookup table // and typeset in boldface. Also, a `definition' index entry must be // generated. Before typesetting identifiers, underlines must be escaped. // // Another issue is how to distinguish between definition and use? Locally // you can't distinguish whether the id `a' is part of `int a' or `a++'. // We'll try to use a global flag `in_decl' that is set to `true' whenever // we think we're just parsing a declaration. ident : id_like | class ID_LIKE [ install(attribute_to_string($2)); ] { "{\\bf " $1 "}\\ \\mbox{\\bf " [ create(escaped_underlines(attribute_to_string($2))) ] "}" "%\n@index defn " $2 "\n" } | class SHORT_ID [ install(attribute_to_string($2)); ] { "{\\bf " $1 "}\\ \\mbox{\\bf " [ create(escaped_underlines(attribute_to_string($2))) ] "}" "%\n@index defn " $2 "\n" } | INT_LIKE class ID_LIKE [ install(attribute_to_string($3)); ] { $1 "\\ {\\bf " $2 "}\\ \\mbox{\\bf " [ create(escaped_underlines(attribute_to_string($3))) ] "}" "%\n@index defn " $3 "\n" } | INT_LIKE class SHORT_ID [ install(attribute_to_string($3)); ] { $1 "\\ {\\bf " $2 "}\\ \\mbox{\\bf " [ create(escaped_underlines(attribute_to_string($3))) ] "}" "%\n@index defn " $3 "\n" } | sync_like id_like { $1 "\\ " $2 } | ident id_like { $1 "\\ " $2 } ; brack_exp : lbrack rbrack { $1 "\\thinspace " $2 } | lbrack exp rbrack | brack_exp ident { $1 "\\ " $2 } ; term : factor | unop term { "\\mathin " $1 $2 } | unorbinop term { "\\mathin " $1 $2 } | incrop term { "\\mathin " $1 $2 } | term incrop { "\\mathin " $1 $2 } ; factor : ident | num | string | lpar rpar { $1 "\\thinspace" $2 } | lpar exp rpar ; decl : block | non_block_stmt ; non_block_stmt : semi { cancel $1 } | exp semi { "\\mathin " $1 "\\mathout" $2 } | break_like semi | break_like exp semi { $1 "\\ \\mathin " $2 "\\mathout" $3 } | sync_like lpar exp rpar decl { $1 "\\ \\mathin " $2 $3 $4 "\\mathout\\ " $5 } | import_head semi | label colon decl { force backup $1 $2 force $3 } | try_stmt | if_block | if_simple | else_head block { $1 "\\ " $2 } | else_head non_block_stmt { $1 indent force $2 outdent } | for_stmt | do_stmt ; import_head : import_like id_like { $1 "\\ " $2 } | import_head dot id_like | import_head dot_star ; if_head : if_like lpar exp rpar { $1 "\\ \\mathin " $2 $3 $4 "\\mathout" } ; if_block : if_head block { $1 "\\ " $2 } ; if_simple : if_head non_block_stmt { $1 indent force $2 outdent } ; else_head : else_like | if_block else_like { $1 "\\ " $2 } | if_simple else_like { $1 force $2 } ; try_stmt : try_like block { $1 "\\ " $2 } | try_stmt finally_like block { $1 "\\ " $2 "\\ " $3 } | try_stmt catch_like lpar exp rpar block { $1 "\\ \\mathin " $2 $3 $4 $5 "\\mathout\\ " $6 } ; label : default_like | case_like exp { $1 "\\ \\mathin " $2 "\\mathout"} | id_like ; do_stmt : do_like block if_head semi { $1 "\\ " $2 "\\ " $3 $4 } | do_like non_block_stmt if_head semi { $1 indent force $2 outdent $3 $4 } ; for_head : for_like lpar for_control rpar { $1 "\\ " $2 $3 $4 } ; for_control : opt_exp semi opt_exp semi opt_exp ; opt_exp : // empty | exp { "\\mathin " $1 "\\mathout" } ; for_stmt : for_head block { $1 "\\ " $2 } | for_head non_block_stmt { $1 indent force $2 outdent } ; // rules to pass comments and ignores through unnoticed binop : BINOP | binop IGNORE | binop COMMENT { $1 "\\qquad" break_space $2 force } ; break_like : BREAK_LIKE | break_like IGNORE | break_like COMMENT { $1 "\\qquad" break_space $2 force } ; case_like : CASE_LIKE | case_like IGNORE | case_like COMMENT { $1 "\\qquad" break_space $2 force } ; catch_like : CATCH_LIKE | catch_like IGNORE | catch_like COMMENT { $1 "\\qquad" break_space $2 force } ; class : CLASS | class IGNORE | class COMMENT { $1 "\\qquad" break_space $2 force } ; colon : COLON | colon IGNORE | colon COMMENT { $1 "\\qquad" break_space $2 force } ; comma : COMMA | comma IGNORE | comma COMMENT { $1 "\\qquad" break_space $2 force } ; default_like : DEFAULT_LIKE | default_like IGNORE | default_like COMMENT { $1 "\\qquad" break_space $2 force } ; dot : DOT | dot IGNORE | dot COMMENT { $1 "\\qquad" break_space $2 force } ; dot_star : DOT_STAR | dot_star IGNORE | dot_star COMMENT { $1 "\\qquad" break_space $2 force } ; do_like : DO_LIKE | do_like IGNORE | do_like COMMENT { $1 "\\qquad" break_space $2 force } ; else_like : ELSE_LIKE | else_like IGNORE | else_like COMMENT { $1 "\\qquad" break_space $2 force } ; extends_like : EXTENDS_LIKE | extends_like IGNORE | extends_like COMMENT { $1 "\\qquad" break_space $2 force } ; finally_like : FINALLY_LIKE | finally_like IGNORE | finally_like COMMENT { $1 "\\qquad" break_space $2 force } ; for_like : FOR_LIKE | for_like IGNORE | for_like COMMENT { $1 "\\qquad" break_space $2 force } ; // here we come across an identifier that's not part of a // `class' or `interface' clause. If it's in the lookup // table then it has already been defined as a class or // interface and so it looks like we're dealing with // a declaration now. // // If it's not in the table, it's got to be in italics and // the index entry depends on the `in_decl' flag. id_like : ID_LIKE { // begin index entry "%\n@index " [ (in_decl == 0) ? create("use ") : create("defn ") ] $1 "\n" // end index entry [ lookup(attribute_to_string($1)) ? create("{\\bf ") : create("{\\it ") ] [create(escaped_underlines(attribute_to_string($1)))] "}" } // don't index short ids but still put correct markup around them: | SHORT_ID { "{" [ lookup(attribute_to_string($1)) ? create("\\bf") : create("\\it") ] " " [create(escaped_underlines(attribute_to_string($1)))] "}" } | CHUNK { $1 force } | id_like IGNORE | id_like COMMENT { $1 "\\qquad" break_space $2 force } ; if_like : IF_LIKE | if_like IGNORE | if_like COMMENT { $1 "\\qquad" break_space $2 force } ; import_like : IMPORT_LIKE | import_like IGNORE | import_like COMMENT { $1 "\\qquad" break_space $2 force } ; incrop : INCROP | incrop IGNORE | incrop COMMENT { $1 "\\qquad" break_space $2 force } ; // INT_LIKE's become id_like, but it looks like a declaration now id_like : INT_LIKE [ in_decl = 1; ] { $1 } ; lbrace : LBRACE | lbrace IGNORE | lbrace COMMENT { $1 "\\qquad" break_space $2 force } ; lbrack : LBRACK | lbrack IGNORE | lbrack COMMENT { $1 "\\qquad" break_space $2 force } ; lpar : LPAR | lpar IGNORE | lpar COMMENT { $1 "\\qquad" break_space $2 force } ; num : NUM | num IGNORE | num COMMENT { $1 "\\qquad" break_space $2 force } ; question : QUESTION | question IGNORE | question COMMENT { $1 "\\qquad" break_space $2 force } ; rbrace : RBRACE | rbrace IGNORE | rbrace COMMENT { $1 "\\qquad" break_space $2 force } ; rbrack : RBRACK | rbrack IGNORE | rbrack COMMENT { $1 "\\qquad" break_space $2 force } ; rpar : RPAR | rpar IGNORE | rpar COMMENT { $1 "\\qquad" break_space $2 force } ; // a semicolon seems to end a declaration semi : SEMI [ in_decl = 0; ] { $1 } | semi IGNORE | semi COMMENT { $1 "\\qquad" break_space $2 force } ; string : STRING | string IGNORE | string COMMENT { $1 "\\qquad" break_space $2 force } ; sync_like : SYNC_LIKE | sync_like IGNORE | sync_like COMMENT { $1 "\\qquad" break_space $2 force } ; try_like : TRY_LIKE | try_like IGNORE | try_like COMMENT { $1 "\\qquad" break_space $2 force } ; unop : UNOP | unop IGNORE | unop COMMENT { $1 "\\qquad" break_space $2 force } ; unorbinop : UNORBINOP | unorbinop IGNORE | unorbinop COMMENT { $1 "\\qquad" break_space $2 force } ; %% /* these functions help to typeset classes. They implement * a simple lookup table to see if an identifier is a * class or what... * * taken from Kernighan/Ritchie: The C Programming Language, p.144ff */ /* form the hash value of a string */ static unsigned hash(char* s) { // cerr << "hash(" << s << ") called." << endl; unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = *s + 31 * hashval; return hashval % HASHSIZE; } /* lookup: look for s in hashtab * * returns a pointer to the found element or NULL if it was not * found. */ static struct nlist* lookup(char* s) { // cerr << "lookup(" << s << ") called." << endl; struct nlist* np; for (np = hashtab[hash(s)]; np != NULL; np = np->next) if (strcmp(s, np->name) == 0) return np; /* found */ return NULL; /* not found */ } /* install: put name in hashtab. * * returns a pointer to the new element if all went well, * returns NULL on error. */ static struct nlist *install(char* name) { // cerr << "install(" << name << ") called." << endl; struct nlist* np; unsigned hashval; if ((np = lookup(name)) == NULL) { /* not found */ np = (struct nlist*) malloc(sizeof(*np)); if (np == NULL || (np->name = strdup(name)) == NULL) return NULL; hashval = hash(name); np->next = hashtab[hashval]; hashtab[hashval] = np; } return np; } /* attibute_to_string - * turn an attribute into a string * * idea: call print() with a strstream * * NB: Output has to be deleted and the strstream properly * terminated before calling .str()! Otherwise, the last * characters are garbeled. */ static char* attribute_to_string( Attribute* a ) { // cerr << "entering attribute to string." << endl; // debug_print("attribute is", a); ostrstream printstream; Latex_cweb_output* o = new Latex_cweb_output(printstream); // o->debug_on(); a->print(*o); delete o; printstream << ends; char* tmp = printstream.str(); //cerr << "attribute to string returning `" << tmp << "'." << endl; return tmp; } // escaped_underines replaces every occurrence of `_' by // the two characters `\_' in a copy of the string pointed to // by s // // the implementation first counts the number of underlines in // the string s and allocates new memory for the string. It then // copies the string byte after byte into the new place and // takes care to insert a `\' before any underline. // // this is a bit dirty as we don't have a chance to free the // allocated space later on, but it's still better than messing // around with yytext. To minimize the amount of memory I have // added a test whether copying is needed or not. static char* escaped_underlines(char* s) { // cerr << "entering escaped underlines with `" << s << "'." << endl; char* tmp = s; int number_of_ul = 0; int left = 0; // s[left] is the next char to copy int right = 0; // place s[left] in tmp[right] // fprintf(stderr, "call of escaped_underlines\n"); // count underlines in s while (*tmp != 0) { if (*tmp == '_') number_of_ul++; tmp++; } // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul); if (number_of_ul == 0) { tmp = s; // skip copying } else { tmp = new char[strlen(s) + number_of_ul + 1]; assert(tmp!=NULL); // now start to copy while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but // some compilers choke on it if (s[left] == '_') { tmp[right] = '\\'; right++; } tmp[right] = s[left]; left++; right++; } tmp[right] = s[left]; /* terminate string */ } // cerr << "escaped underlines returning `" << tmp << "'." << endl; return(tmp); } /* debugging function */ static void debug_print( char* this_is, Attribute* stuff ) { cerr << "*** " << this_is << ":" << endl; Latex_cweb_output os(cerr); stuff->print(os); } /* * $Log: javafx.fg,v $ * Revision 1.1 1997/07/09 14:24:27 gaertner * Initial revision * * Revision 1.3 1997/07/08 19:08:10 theedge * small additions to commmentary * * Revision 1.2 1997/07/08 18:48:34 theedge * Versions that work. * * Revision 1.1 1997/06/26 16:23:56 theedge * Initial revision * */ pretzel-2.0n-2/contrib/noweb/index.list0000644000000000000000000000041606360666405016645 0ustar rootrootthis directory & noweb prettyprinters for Pretzel by Felix Gaertner cee.html & Test of C with HTML as back end cee.latex & rudimentary C with LaTeX as target general & general stuff for interfacing with noweb java.latex & good Java prettyprinter that also does indexing pretzel-2.0n-2/contrib/noweb/general/0000755000000000000000000000000010765026553016253 5ustar rootrootpretzel-2.0n-2/contrib/noweb/general/errors.nw0000644000000000000000000000464306255317024020137 0ustar rootroot% Copyright 1991 by Norman Ramsey. All rights reserved. % See file COPYRIGHT for more information. \subsection{Error messages} Here is a big set of functions that other places can call to issue error messages. It might be worth implementing these as macros so they could indicate the file name and line number in the source of where they were called. [[errorlevel]] is an integer that says how bad the worst error so far has been. [[newerrorlevel]] will update it conditionally. Some day we should hide it and give the world a function call that queries it. <<*>>= #include #include #include #include #include "errors.h" <> @ I track degrees of error as they occur. <

>= enum errorlevel { Normal=0, Warning, Error, Fatal, Impossible }; extern enum errorlevel errorlevel; @ %def errorlevel <>= enum errorlevel errorlevel = Normal; @ The rest is just varying flavors of error messages. <
>= void errormsg(enum errorlevel level, char *s, ...); #define overflow(S) errormsg(Fatal,"Capacity exceeded: %s", S) #define impossible(S) errormsg(Impossible, "This can't happen: %s", S) #define checkptr(P) do { if (!(P)) overflow("memory"); } while (0) @ %def errormsg overflow impossible checkptr <>= void errormsg(enum errorlevel level, char *s,...) { va_list args; /* see K&R, page 174 */ va_start(args,s); <> va_end(args); if (level >= Fatal) exit(level); } @ %def errormsg <
>= void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...); <>= void errorat(char *filename, int lineno, enum errorlevel level, char *s, ...) { va_list args; /* see K&R, page 174 */ va_start(args,s); fprintf(stderr, "\"%s\", line %d: ", filename, lineno); <> va_end(args); if (level >= Fatal) exit(level); } @ %def errorat <>= if (level > errorlevel) errorlevel = level; vfprintf(stderr, s, args); fprintf(stderr,"\n"); @ Some older machines don't do [[vfprintf]]; here's an implementation: <>= extern int _doprnt(const char *format, va_list args, FILE *stream); int vfprintf(FILE *stream, const char *format, va_list arg) { return _doprnt(format,arg,stream); } pretzel-2.0n-2/contrib/noweb/general/strsave.nw0000644000000000000000000000073506255317025020311 0ustar rootroot% Copyright 1991 by Norman Ramsey. All rights reserved. % See file COPYRIGHT for more information. <
>= char *strsave (char *s); /* returns a pointer to a fresh copy of s */ <<*>>= #include #include #include #include "strsave.h" #include "errors.h" char *strsave (char *s) { /* added cast to char*, FG Tue Mar 26 11:09:52 MEZ 1996 */ char *t = (char*) malloc (strlen(s)+1); checkptr(t); strcpy(t,s); return t; } pretzel-2.0n-2/contrib/noweb/general/getline.nw0000644000000000000000000000534510111701037020235 0ustar rootroot% Copyright 1991 by Norman Ramsey. All rights reserved. % See file COPYRIGHT for more information. @ \section{Utility functions} \subsection{Line-oriented input} [[getline]] is reads in the next line, no matter how long it is, expanding tabs. I allocate more and more space for the line, until I've read a whole line or until I run out of space, whichever comes first. The buffer grows in size exponentially, so the cost in overhead is roughly the logarithm of the length of the longest line. @ [[getline]] reuses the same internal buffers over and over, so subsequent calls destroy the results of previous calls. <<*>>= #define START_SIZE 128 /* initial buffer size */ #include #include #include #include "columns.h" #include "errors.h" #include "getline.h" static char *buf1 = NULL, *buf2 = NULL; /* lines without, with tabs expanded */ static int buf_size = START_SIZE; /* size of both buffers if non-NULL */ <> @ %def START_SIZE buf_size buf1 buf2 <
>= char *getline_expand (FILE *fp); /* grab a line in buffer, return new buffer or NULL for eof tabs in line are expanded according to tabsize */ char *getline (FILE *fp); /* grab a line in the buffer, return a new buffer or NULL for eof no expansion of tabs */ @ <>= void new_buffers(void) { checkptr(buf1 = (char *) realloc(buf1, buf_size)); checkptr(buf2 = (char *) realloc(buf2, buf_size)); } <>= char *getline (FILE *fp) { <> buf1=fgets(buf1, buf_size, fp); if (buf1==NULL) return buf1; /* end of file */ while (buf1[strlen(buf1)-1] != '\n') { /* failed to get whole line */ buf_size *= 2; new_buffers(); if (fgets(buf1+strlen(buf1),buf_size-strlen(buf1),fp)==NULL) return buf1; /* end of file */ } return buf1; } @ %def getline <>= char *getline_expand (FILE *fp) { char *s, *t; int width; if (getline(fp)==NULL) return NULL; < buf_size - 1]], allocate new buffers>> s = buf1; t = buf2; width=0; while (*s) if (*s=='\t' && tabsize > 0) { do { *t++ = ' '; width++; } while (width % tabsize != 0); s++; } else { *t++ = *s++; width++; } *t='\0'; return buf2; } @ %def getline_expand <>= if (buf1==NULL) { checkptr(buf1 = (char *) malloc (buf_size)); checkptr(buf2 = (char *) malloc (buf_size)); } < buf_size - 1]], allocate new buffers>>= if (columnwidth(buf1) > buf_size - 1) { while (columnwidth(buf1) > buf_size - 1) buf_size *= 2; new_buffers(); } pretzel-2.0n-2/contrib/noweb/general/testcode.nw0000644000000000000000000000077206635712013020433 0ustar rootroot\documentclass{article} \usepackage{noweb,pretzel-noweb} \begin{document} This is a small noweb file containing test code for the [[prettytest]] filter generated in this directory. The prettyprinter understands and prettyprints a sequence of identifiers, one line each. Here's some noweb code to prettyprint. <<*>>= anidentifier; anotherone; andstillanother @ <>= @ <>= @ <>= anidentifier anotherone @ \end{document} pretzel-2.0n-2/contrib/noweb/general/index.list0000644000000000000000000000047506360667562020274 0ustar rootrootthis directory & Interface between noweb and Pretzel Makefile & The Makefile README & more Information columns.nw & files from the noweb distribution needed here errors.nw & getline.nw & match.nw & strsave.nw & pretty.nw & nowebpretzelpp.nw & the actual interface file test.fg & Test files test.ft & testcode.nw & pretzel-2.0n-2/contrib/noweb/general/match.nw0000644000000000000000000000242106255317024017707 0ustar rootroot\subsection{Code to recognize [[noweb]] markup on input} We recognize the input using matching functions, which can find [[@begin]], [[@end]], and other useful information. <
>= extern int is_keyword(char *line, char *keyword); extern int is_begin(char *line, char *type); extern int is_end(char *line, char *type); extern int is_index(char *line, char *type); <<*>>= #include #include "match.h" static int matches(char *line, char *search) { return !strncmp(line,search,strlen(search)); } @ On 24 March 1996, I changed this to accept zero as a terminator because I strip newlines in the prettyprinter. Too bad if we just got worse at detecting bogus filters. <<*>>= int is_keyword(char *line, char *keyword) { char low_at_sign = '@'; return *line==low_at_sign && matches(line+1,keyword) && (line[strlen(keyword)+1]==' ' || line[strlen(keyword)+1]=='\n' || line[strlen(keyword)+1]=='\0'); } int is_begin(char *line, char *type) { return is_keyword(line,"begin") && matches(line+1+6,type); } int is_end(char *line, char *type) { return is_keyword(line,"end") && matches (line+1+4,type); } int is_index(char *line, char *type) { return is_keyword(line,"index") && matches(line+1+6,type); } @ %def is_keyword is_begin is_end is_index pretzel-2.0n-2/contrib/noweb/general/README0000644000000000000000000000251506255316574017142 0ustar rootrootREADME for contrib/noweb/general This directory includes all files necessary to build pretzel prettyprinting filters for noweb. The main parts of these files comes directly from the noweb distribution and are copyright by Norman Ramsey. These files are: columns.nw errors.nw getline.nw match.nw pretty.nw strsave.nw (Permission to include them in the pretzel distribution has been kindly granted by Norman Ramsey.) The file pretty.nw contains an API for a noweb prettyprinting function and an additional main() program that calls this prettyprinter. An additional file nowebpretzelpp.nw (by Felix Gaertner :-) interfaces a Pretzel prettyprinter with the noweb prettyprinter API. All objects of these files (except pretty.nw) are added to the Pretzel library (libpretzel.a) when you `make release'. Also, the object file pretty.o is copied to the Pretzel library directory as nowebpp.o so that pretzel-it can find it when invoked with the noweb option (-n). The following make'able targets are defined: *none* or prettytest to make a test prettyprinting filter for noweb regression run noweave using prettytest on testcode.nw clean clean up all objects clobber clean up C sources, header files and executables release copy the main nowebpp.o object to the library dir and add necessary objects to pretzel library pretzel-2.0n-2/contrib/noweb/general/pretty.nw0000644000000000000000000002046306474266075020164 0ustar rootroot\section{Prettyprinting} \subsection{API for prettyprinting} Here is a suitable API for a prettyprinter for noweb. Input to be prettyprinted is a sequence of strings, newlines, and chunks used. A [[STRING]] is always free of newlines. <>= typedef enum parttype { START_OF_CHUNK=1, END_OF_CHUNK, STRING, USE_CHUNK, NEWLINE, LITERAL, DEFINITION, WHATSIT } Parttype; @ The prettyprinter calls back into the application as follows: <>= typedef void (*PrettyPrinterCallback) (void *closure, Parttype type, char *contents); @ The [[contents]] must be \begin{quote} \begin{tabular}{ll} [[START_OF_CHUNK]]&The name of the chunk being prettyprinted\\ [[END_OF_CHUNK]]&[[NULL]]\\ [[STRING]]&A string with no newlines\\ [[LITERAL]]${}^*$&A string with no newlines, to get no further formatting\\ [[USE_CHUNK]]&The name of the chunk referred to\\ [[NEWLINE]]&[[NULL]]\\ [[DEFINITION]]${}^*$&An identifier whose definition is in this chunk.\\ [[WHATSIT]]&An uninterpreted string passed to the callback function \end{tabular} \end{quote} Items marked with a star ($*$) are legal only when the prettyprinter is calling back into the application. The identifier given in [[DEFINITION]] isn't printed, so if the prettyprinter wants to print it, it has to send it twice. @ The prettyprinter exports two calls to the application. <>= typedef struct prettyprinter *PrettyPrinter; extern PrettyPrinter new_prettyprinter(PrettyPrinterCallback callback, void *closure); extern void prettyprint(PrettyPrinter pp, Parttype type, char *contents); @ The prettyprinter accepts calls to the [[prettyprint]] procedure. Any call to [[prettyprint]] may result in one or more callbacks to the procedure registered when [[new_prettyprinter]] is called. For any given [[PrettyPrinter]], the application must call [[prettyprint]] with [[type==END_OF_CHUNK]] exactly once, and that call must be the last call. <
>= <> @ \subsection{Calling the prettyprinter} The assumption here is that we have zero or more prettyprinters satisfying the interface above---what are the mechanics of getting something prettyprinted. We select a prettyprinter based on the name of the root chunk. Because we want to support either a two-pass or one-pass algorithm, we don't say how lines will come in or go out, but we do say that we will strip all the trailing newlines. <>= void pretty (char *getline(void *in), void *in, void putline(void *out, char *line), void *out, PrettyPrinter make_pp(void *cl, char *name), void *cl) { char *line = NULL; /* buffer for input */ PrettyPrinter pp; Location loc; while ((line = getline(in)) != NULL) { <> <> putline(out, line); for (line = getline(in); line && !is_keyword(line,"defn") && !is_keyword(line,"text"); line = getline(in) ) putline(out, line); insist(line,"defn","code chunk had no definition line"); putline(out, line); pp = make_pp(cl, line+6); /* use chunk name */ /* FG: added following line to let prettyprinter know what * chunk it's prettyprinting. */ if (pp) prettyprint(pp, START_OF_CHUNK, line+6); if (!pp) { <>; continue; } for (; line && !is_keyword(line, "nl") ;) { line = getline(in); putline(out, line); } insist(line,"nl","definition line not followed by newline"); loc.lineno++; for (line = getline(in); line != NULL && !is_end(line,"code"); line = getline(in)) { <> if (is_keyword(line,"nl")) { prettyprint(pp, NEWLINE, NULL); } else if (is_keyword(line,"text")) { prettyprint(pp, STRING, line+1+4+1); } else if (is_keyword(line,"use")) { prettyprint(pp, USE_CHUNK, line+1+3+1); } else { prettyprint(pp, WHATSIT, line); } } prettyprint(pp, END_OF_CHUNK, NULL); <> putline(out, line); } } <>= if (!is_begin(line, "code")) { putline(out, line); continue; } <>= while ((line = getline(in)) != NULL) { putline(out, line); if (is_end(line, "code")) break; } @ <>= { if (is_keyword(line, "nl") || is_index(line, "nl")) { loc.lineno++; } else if (is_keyword(line,"file")) { loc.filename = strsave(line + 6); loc.lineno = 1; } else if (is_keyword(line, "line")) { <> loc.lineno--; } } @ <>= { char *temp = line+6; <> loc.lineno = atoi(temp); } <>= { char *p; for (p = temp; *p; p++) if (!isdigit(*p)) errormsg(Error, "non-numeric line number in `@line %s'", temp); } <>= void insist(char *line, char *keyword, char *msg) { <> if (!is_keyword(line,keyword)) impossible(msg); } <>= if (line==NULL) { impossible("End of file occurred in mid-module"); } <>= void insist(char *line, char *keyword, char *msg); @ \subsection{Simple callback procedure} We've got a callback to do I/O <>= typedef struct io { FILE *out; void (*putline)(void *out, char *line); } *IO; static void write_pretty(void *closure, Parttype type, char *contents) { IO io = (IO) closure; switch(type) { case START_OF_CHUNK: break; case END_OF_CHUNK: break; case STRING: fprintf(io->out, "@text %s\n", contents); break; case LITERAL: fprintf(io->out, "@literal %s\n", contents); break; case USE_CHUNK: fprintf(io->out, "@use %s\n", contents); break; case NEWLINE: io->putline(io->out, "@nl"); break; case DEFINITION: fprintf(io->out, "@index defn %s\n", contents); break; case WHATSIT: io->putline(io->out, contents); break; default: assert(0); } } @ \subsection{Sketch for a two-pass driver} The best plan would be to use a two-pass driver. On the first pass it would \begin{itemize} \item Read in all lines and builds a def-use tree. \item Decide on a prettyprinter for each root, either using the root name or a suffix (and probably based on info from the command line as well as defaults). \item Propagate info from parents to children. Inconsistent children (distinct prettyprinters) become new roots. \end{itemize} Then on the second pass it could use the propagated info to select a prettyprinter for each chunk. \subsection{One-pass driver} This just uses a single prettyprinter. This means get and put are just I/O. <>= static char *get_stripped(void *in) { FILE *fp = (FILE *)in; char *line = getline(fp); if (line) { int i = strlen(line) - 1; if (i >= 0 && line[i] == '\n') line[i] = 0; } return line; } static void put_stripped(void *out, char *line) { FILE *fp = (FILE *)out; fputs(line, fp); fputc('\n', fp); } @ If we only ever use a single prettyprinter, we make the closure the I/O closure. [As a trick, we return no prettyprinter if the chunk name has a blank. Commented out for testing purposes.] <>= static PrettyPrinter make_pp(void *cl, char *name) { // if (strchr(name, ' ')) return NULL; return new_prettyprinter(write_pretty, cl); } @ The program is always a filter, so it uses stdin and stdout. <>= main (int argc, char *argv[]) { struct io io; io.out = stdout; io.putline = put_stripped; pretty(get_stripped, stdin, put_stripped, stdout, make_pp, &io); return 0; } @ \subsection{Boilerplate} <<*>>= #include #include #include #include #include #include "strsave.h" #include "getline.h" #include "match.h" #include "errors.h" #include "pretty.h" typedef struct location { /* identify lines of source */ char *filename; int lineno; } Location; <> <> <> pretzel-2.0n-2/contrib/noweb/general/test.fg0000644000000000000000000000025406635712216017550 0ustar rootroot/* pretzel formatted grammar for testing the noweb filter */ %token ID_TYPE SEMI %% stmt : id | id SEMI stmt { $1 $2 force "\n" $3 } ; id : ID_TYPE ; pretzel-2.0n-2/contrib/noweb/general/index.html0000644000000000000000000000260206360667621020253 0ustar rootroot Index file for directory "pretzel/contrib/noweb/general" of Pretzel distribution

Index file for directory "pretzel/contrib/noweb/general" of Pretzel distribution

Files and directories are:

this directory

    Interface between noweb and Pretzel
Makefile
    The Makefile
README
    more Information
columns.nw
    files from the noweb distribution needed here
errors.nw
getline.nw
match.nw
strsave.nw
pretty.nw
nowebpretzelpp.nw
    the actual interface file
test.fg
    Test files
test.ft
testcode.nw

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 13:01:37 MESZ 1997 pretzel-2.0n-2/contrib/noweb/general/nowebpretzelpp.nw0000644000000000000000000005241110765024664021705 0ustar rootroot% noweb source % % $Id: nowebpretzelpp.nw,v 1.8 1999/01/19 10:59:54 felix Exp $ % % History at end % \documentclass{article} \usepackage{noweb} \usepackage{pretzel-latex} \begin{document} \title{\texttt{nowebpretzelpp.nw} \\ A Prettyprinter for {\tt noweb}} \author{Felix G\"artner} \maketitle \tableofcontents \section{Introduction} This document describes the interface and implementation of a prettyprinter for {\tt noweb}. It is written in C++ and conforms to an API given to me by Norman Ramsey. \section{Interface} [This section is the API by Norman Ramsey. Additional text by the current author is put in angled brackets.] Here is a suitable API for a prettyprinter for noweb. Input to be prettyprinted is a sequence of strings, newlines, and chunks used. A [[STRING]] is always free of newlines. <>= typedef enum parttype { START_OF_CHUNK=1, END_OF_CHUNK, STRING, USE_CHUNK, NEWLINE, LITERAL, DEFINITION, WHATSIT } Parttype; @ The prettyprinter calls back into the application as follows: <>= typedef void (*PrettyPrinterCallback) (void *closure, Parttype type, char *contents); @ The [[contents]] must be \begin{quote} \begin{tabular}{ll} [[START_OF_CHUNK]]&The name of the chunk being prettyprinted\\ [[END_OF_CHUNK]]&[[NULL]]\\ [[STRING]]&A string with no newlines\\ [[LITERAL]]${}^*$&A string with no newlines, to get no further formatting\\ [[USE_CHUNK]]&The name of the chunk referred to\\ [[NEWLINE]]&[[NULL]]\\ [[DEFINITION]]${}^*$&An identifier whose definition is in this chunk.\\ [[WHATSIT]]&An uninterpreted string passed to the callback function \end{tabular} \end{quote} Items marked with a star ($*$) are legal only when the prettyprinter is calling back into the application. The identifier given in [[DEFINITION]] isn't printed, so if the prettyprinter wants to print it, it has to send it twice. @ The prettyprinter exports two calls to the application. <>= typedef struct prettyprinter *PrettyPrinter; extern PrettyPrinter new_prettyprinter(PrettyPrinterCallback callback, void *closure); extern void prettyprint(PrettyPrinter pp, Parttype type, char *contents); @ The prettyprinter accepts calls to the [[prettyprint]] procedure. Any call to [[prettyprint]] may result in one or more callbacks to the procedure registered when [[new_prettyprinter]] is called. For any given [[PrettyPrinter]], the application must call [[prettyprint]] with [[type==END_OF_CHUNK]] exactly once, and that call must be the last call. <

>= <> @ \section{Implementation} \subsection{Overview} The implementation will use a prettyprinter generated by the Pretzel system. A Pretzel prettyprinter comes in the form of a class: % \begin{verbatim} // abstract base class of prettyprinter: #include #include"attr.h" #include"output.h" class Pparse { public: Pparse() {}; ~Pparse() {}; virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*) = 0; }; // actual prettyprinter: #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; \end{verbatim} % The idea of the implementation is to translate calls to the API functions into suitable sequences for the Pretzel prettyprinter. This is not the nicest way of doing it, but it seems the fastest solution at the moment. (A more elegant way would be to change Pretzel internals, but that is a different story.) I have analyzed the code of {\tt pretty.nw} and am using it as the filter which generates the calls to this prettyprinter. There will be calls using the [[START_OF_CHUNK]], [[NEWLINE]], [[STRING]], [[USE_CHUNK]] and [[WHATSIT]] part types. The final call to [[prettyprint]] is with an [[END_OF_CHUNK]]. Here's an overview over the implementation. <<*>>= /* implementation of a noweb prettyprinter using Pretzel */ <
> <> <> <> @ Of course, we include our own header file, which is {\tt pretty.h} from the noweb distribution. <
>= #include "pretty.h" @ Because a Pretzel prettyprinter needs to see the entire text before it can start to prettyprint, we have to wait until an [[END_OF_CHUNK]] is sent, collecting all the strings and newlines coming in along the way. Having done this, we have a view of the entire code part, including chunk names, etc.~and can send all this to the Pretzel prettyprinting class (using C++ [[stringstream]]s). Pretzel returns a long string again which is chopped up into lines and sent back to the application via the callback function. There are a few problems here: % \begin{itemize} \item Chunk uses have to be known to the prettyprinter in order to get the formatting (indentation etc.) right. This means that they have to be part of the prettyprinting grammar of pretzel. \item The [[WHATSIT]] parttypes would mess up the prettyprinter if they were sent to it because they will inevitably be seen by the parser and would mess up parsing! So we sent a [[WHATSIT]] directly back to the application if we see it. \end{itemize} \subsection{The Actual Prettyprinter} This the actual prettyprinter. We'll use a [[struct]] to conform with the API. A [[class]] would be nicer though. Inside the prettyprinter we have to store the callback function and the [[closure]] parameter, which is a kind of user data (?). Also, we need a [[stringstream]] object to collect all the strings coming in and a string to store the name of the chunk in case we need to do debug output. <>= struct prettyprinter { PrettyPrinterCallback ppcb; void* user_data; std::stringstream* to_be_pped; /* space for collecting code */ char* chunk_name; /* name of the chunk being pp'ed */ }; @ <
>= #include @ \subsection{The Prettyprinter Functions} To create a new prettyprinter for a chunk, we simply create a new [[PrettyPrinter]] object and store the interesting stuff in the right places. (Sorry, this is C++, but we're using [[iostreams]] anyway.) <>= PrettyPrinter new_prettyprinter( PrettyPrinterCallback callback, void* closure) { PrettyPrinter pp = (PrettyPrinter) malloc(sizeof(struct prettyprinter)); pp->ppcb = callback; pp->user_data = closure; pp->to_be_pped = new std::stringstream; return(pp); } @ <
>= #include @ Now for the actual [[prettyprint]] function. Its task is to prettyprint the incoming strings and send them back to the application via the callback. Internally, [[prettyprint]] is a giant switch. It looks at the type of thing that is coming in and decides what to to. <>= void prettyprint(PrettyPrinter pp, Parttype type, char *contents) { switch (type) { <> default : cerr << "Oops. There's a parttype I don't understand." << endl; exit(1); } } @ Now let's look at the different cases. We know from the start that the case of [[END_OF_CHUNK]] will be the most complicated, because all work is done there. So let's leave this until the end. We'll have the simple cases first. @ One of the first calls to the prettyprinter will be one with [[type==START_OF_CHUNK]]. This call doesn nothing but remember the chunk name. This is okay since typesetting the chunk name is done by the usual {\tt noweb} back end. String contents have to be copied. <>= case START_OF_CHUNK : pp->chunk_name = (char*) malloc(strlen(contents)+1); strcpy(pp->chunk_name, contents); break; @ <>= delete pp->chunk_name; @ When [[type==STRING]], the incoming string is a bit of code that needs to be mangled and thus simply appended to the [[stringstream]] within the prettyprinter. <>= case STRING : *(pp->to_be_pped) << contents; break; @ A similar thing is done when a [[NEWLINE]] arrives. <>= case NEWLINE : *(pp->to_be_pped) << "\n"; break; @ Now for one of the tricky bits, the [[USE_CHUNK]] case. Normally, we would call the callback with the chunk name at that moment, when the prettyprinted text before the chunk name has been output (via the callback) and before the text following it is output. Unfortunately, in the current version of Pretzel, we do not have real control where the chunk name appears in the output and thus don't have an obvious chance of calling the callback directly here. We use a trick here: We know that we'll chop up the prettyprinted output into lines and output these lines one at a time later on. So we'll put a full line of text referring to the chunk into the prettyprinted output. This line has to be spotted by the prettyprinter and left unchanged. When the prettyprinter has done his work, we'll check all the lines for their starting characters and call the callback with [[type==USE_CHUNK]] if a line starts with [[@use]]. <>= case USE_CHUNK : *(pp->to_be_pped) << "\n@use " << contents << "\n"; break; @ The last case for now is the [[WHATSIT]] case. These things can be ignored by the pretzel prettyprinter but they will nevertheless have to be mangled by it. We follow the same plan as above and add the incoming line to the string that is to be prettyprinted. The prettyprinter has to spot this line and leave it unchanged. We assume that these lines have an [[@]] sign at their beginning. <>= case WHATSIT : *(pp->to_be_pped) << "\n" << contents << "\n"; break; @ If an [[END_OF_CHUNK]] is received, we expect it to be the last call to the current prettyprinter. All code sent to us before has to be prettyprinted now and output through the callback to the application. This is where the Pretzel function comes into action. Say, we have a Pretzel prettyprinter for your favourite programming language. We need to include its header to be able to use it. <
>= #include "Ppparse.h" @ Ok, now we can outline the case. In general, we'll top off the string and feed it to the [[prettyprint]] function. This will return stuff on an [[ostream]], which is replaced again by a [[stringstream]] by us. As most prettyprinters generated by Pretzel are a little selective concerning the input that they can handle, we'll check whether or not parsing was successfull by inspecting the return value of the [[prettyprint]] function. (This is a to date undocumented feature. The selectiveness is related to the complexity of writing really good prettyprinting grammars that can handle everything.) If prettyprinting failed, we'll output the stuff in normal noweb [[verbatim]] mode (the flag [[pp_succeeded]] is used to hold this information later).. Note the initialization values for the two flags: a value of 1 for [[is_empty]] ensures that the check for emptyness works. A value of 0 for [[pp_succeeded]] ensures that the standard \texttt{noweb} way of textoutput is used and so no superfluous message of type ``having problems prettyprinting chunk xyz'' appears. <>= case END_OF_CHUNK : { std::ostringstream has_been_pped; Ppparse pretzelpp; *(pp->to_be_pped) << ends; /* end up the string */ char* to_be_pped_string = (char*)pp->to_be_pped->str().c_str(); int is_empty = 1; // empty by default int pp_succeeded = 0; // didn't succeed by default <> if (is_empty == 1) { // cerr << "String is empty" << endl; has_been_pped << "\n" << ends; } else { <> } <> delete to_be_pped_string; } <> break; @ In case we have a truly empty chunk, we must take care not to call [[prettyprint]] as \pretzel{} cannot deal well with truly empty chunks. Here, a chunk is considered empty if it contains only newlines and spaces or if it is really empty (length is 0). <>= int l = strlen(to_be_pped_string); // look if there is a non newline or space int i = 0; while (i>= if (getenv("PRETZEL_NOWEB_DEBUG") != NULL) // stdlib.h already included pretzelpp.debug_on(); else pretzelpp.debug_off(); @ Now the actual call to the prettyprinter is made. The return value designated if prettyprinting was successfull (0) or not (1). According to this value, output of the prettyprinted stuff is different. <>= pp_succeeded = pretzelpp.prettyprint( pp->to_be_pped, &has_been_pped); /* prettyprint! */ has_been_pped << ends; /* top off string */ @ In case prettyprinting succeeded, we'll simply chop the stuff in [[has_been_pped]] into lines and output them to the application as described in the interface. We'll look at the successfull case first and then handle the unsuccessfull case. <>= if (pp_succeeded == 0) { <> } else if (pp_succeeded == 1) { cerr << "having problems prettyprinting chunk <<" << (char*) pp->chunk_name << // leave line break so noweb doesn't spot a module ">>, using verbatim noweb output" << endl; <> } else { cerr << "noweb prettyrinter internal error: illegal yyparse return value" << ends; } @ The text which comes from the prettyprinter will probably not look faintly as nice as the original code: Special macros will be added (in the \LaTeX{} case), indentation will have changed, identifiers may have swapped places. This is why we'll send the individual lines as [[LITERAL]] lines to the application. It will ensure that the line will not get mangled further by {\tt noweb} back ends. If we encounter a line beginning with [[@]], this is a line to be sent to the application directly. Assuming that the above lines haven't been changed by the prettyprinter, this case will cover the [[USE_CHUNK]] case as well as all other cases of {\tt noweb} keywords. We'll encircle the output with the \LaTeX{} {\tt ppcode} environment to get the output right. We also use [[strsep]] instead of [[strtok]] because the latter can't handle empty fields (see entry in the Pretzel diary of Dec 16, 1998). However, [[strsep]] isn't as portable as [[strtok]] (reported by Denis Roegel), and so we'll use our private version of [[strsep]] called [[LYstrsep]]. It is borrowed from the latest distribution of Lynx which suffered from the same problem. The variable [[lookahead]] is introduced for reasons explained below. <>= char* entire_pped_code = (char*)has_been_pped.str().c_str(); (pp->ppcb)(pp->user_data, LITERAL, "\\begin{ppcode}"); char* line = LYstrsep(&entire_pped_code, "\n"); if (line != NULL) { char* lookahead = LYstrsep(&entire_pped_code, "\n"); do { // cerr << "*** got line : " << line << endl; if (strlen(line) == 0) { <> } else { if (*line == '@') { (pp->ppcb)(pp->user_data, WHATSIT, line); } else { (pp->ppcb)(pp->user_data, LITERAL, line); <> } } line = lookahead; lookahead = LYstrsep( &entire_pped_code, "\n" ); } while ( line != NULL ); } (pp->ppcb)(pp->user_data, LITERAL, "\\end{ppcode}"); @ There's a kreeping bug in the code above. Look at the following example: Assume that the prettyprinter gets something like this to eat (newlines written explicitly): % \begin{verbatim} while i<0 do\n \n @use Do foo\n \n if bla;\n \end{verbatim} % The corresponding input could have looked something like this: % \begin{verbatim} while i<0 do if bla; \end{verbatim} % On the left you see how the loop defined above will output the code. On the right you see how it should be: % \begin{verbatim} @literal while i<0 do @literal while i<0 do @nl @nl @literal [4 spaces] @literal [4 spaces] @nl @use Do foo @use Do foo @nl @nl @literal if bla; @literal if bla; @nl @nl \end{verbatim} % The difference is the spurious [[@nl]]. It is the result from having to distinguish ``normal'' newlines from newlines in fron of chunk uses. Possible cure: send newline only if \emph{no} chunk follows. A chunk follows if the next line begins with [["@use "]] (this is why we need the [[lookahead]]). <>= // printf("about to strlen [%s][%s]!!!!!!!!\n", line, lookahead); if ((lookahead != NULL) && ((strlen(lookahead) >= 5) && (strncmp(lookahead, "@use ", 5) == 0))) { /* don't emit newline */ } else { (pp->ppcb)(pp->user_data, NEWLINE, NULL); } @ @ Finally, it's our responsibility to cleanup the output [[stringstream]], because we've called the [[str()]] function on it. <>= delete entire_pped_code; @ Now for the unsuccessfull case of prettyprinting. In this case we don't need to use the stuff in [[has_been_pped]] since it's contents are meaningless. The value of [[to_be_pped]] should be output just as it would have been without Pretzel. Note that none of the other cases in the [[prettyprint]] switch calls the callback function and so nothing wrong has happened up to now. We simply pass everything through as if nothing had happened. Note that normal lines are passed as [[STRING]]s to the application and not as [[LITERAL]]s. <>= char* to_be_pped_string = (char*)pp->to_be_pped->str().c_str(); (pp->ppcb)(pp->user_data, LITERAL, "\\pretzelnwcodeimitation{}"); char* line = LYstrsep(&to_be_pped_string, "\n"); do { if (strlen(line) == 0) { (pp->ppcb)(pp->user_data, NEWLINE, NULL); continue; } if (*line == '@') { (pp->ppcb)(pp->user_data, WHATSIT, line); } else { (pp->ppcb)(pp->user_data, STRING, line); (pp->ppcb)(pp->user_data, NEWLINE, NULL); } } while ( (line = LYstrsep( &to_be_pped_string, "\n" )) != NULL ); @ Finally, here's the [[LYstrsep]] routine borrowed from the Lynx distribution 2.8.2 at \texttt{http://www.slcc.edu/lynx/current/}) (the filenames were \texttt{src/LYStrings.h} and \texttt{src/LYStrings.c}). <>= static char *LYstrsep(char **stringp, const char *delim) { char *tmp, *out; if (!stringp || !*stringp) /* nothing to do? */ return 0; /* then don't fall on our faces */ if (!**stringp) { /* empty string: */ *stringp = 0; /* let caller see he's done; */ return 0; /* no tokens in an empty string */ } out = *stringp; /* save the start of the string */ tmp = strpbrk(*stringp, delim); if (tmp) { *tmp = '\0'; /* terminate the substring with \0 */ *stringp = ++tmp; /* point at the next substring */ } else *stringp = 0; /* this was the last substring: */ /* let caller see he's done */ return out; } @ As there's still a reference to [[strpbrk]] we still must include the [[string.h]] header file. <
>= #include @ \end{document} % % $Log: nowebpretzelpp.nw,v $ % Revision 1.8 1999/01/19 10:59:54 felix % strsep is not a good candidate to use since it is really not very % portable (Denis B. Roegel reports). Used LYstrsep, an implementation % of strsep from the Lynx distribution 2.8.2 (thanks for Denis for % pointing this out). % % Revision 1.7 1998/12/16 11:15:11 felix % Fixed the strtok bug: strtok can't manage empty sequences, using strsep % instead. Also managed to emit newlines only when necessary. % % Revision 1.6 1998/02/24 15:18:56 gaertner % Handles empty chunks better now and emits the % \pretzelnwfake... macro before standard noweb verbatim chunks. % % Revision 1.5 1998/02/23 13:10:30 gaertner % Cleaned up code in END_OF_CHUNK case. Outputs debug info now % in case it can't prettyprint. For this purpose the first call % to prettyprint with START_OF_CHUNK is remembered. % % Revision 1.4 1998/02/23 09:38:23 gaertner % Changed document title. % % Revision 1.3 1996/12/16 19:06:29 gaertner % release 2.0 % % Revision 1.2 1996/12/05 09:09:54 gaertner % Can handle empty chunks now. Removed debug output. % % Revision 1.1 1996/12/04 17:09:17 gaertner % Initial revision % % % pretzel-2.0n-2/contrib/noweb/general/Makefile0000644000000000000000000000677706635711656017742 0ustar rootroot# $Id: Makefile,v 1.4 1998/06/11 10:56:53 felix Exp $ #---------------------------------------------------------------------- # # Makefile for a noweb-pretzel combination # # see README for details # #---------------------------------------------------------------------- # prefix of .ft and .fg files of the small test language TESTLANG = test # all sources generated from noweb files SRCS = pretty.h errors.h getline.h match.h strsave.h columns.h \ pretty.c errors.c getline.c match.c strsave.c columns.c \ nowebpretzelpp.c # this object contains the main() function of the filter and # is linked to any new noweb prettyprinting filter by pretzel-it NWPPMAINOBJ = pretty.o # these are the other objects that are needed to build the main filter # program that calls the prettyprinting function. The actual # prettyprinter is a seperate set of objects. NWPPOBJS = errors.o getline.o match.o strsave.o columns.o # this is the object that interfaces a pretzel prettyprinter with # the noweb prettyprinter API NWPRETZELPPOBJS = nowebpretzelpp.o # these are the objects that implement a test prettyprinter for this # directory. Normally, these files must be supplied by the user and # determine how the prettyprinted output looks NWPRETZELTESTOBJS = test.tab.o test.lex.o #---------------------------------------------------------------------- # which compiler are you using? CC=g++ # make the CFLAGS point to the pretzel installation directorys: CFLAGS=-I../../../include -L../../.. -lpretzel -g NOWEAVE = noweave NOTANGLE = notangle CPIF = > .SUFFIXES: .nw .tex .dvi .h .nw.tex: $(NOWEAVE) -delay -index $*.nw >$*.tex .nw.c: $(NOTANGLE) -L $*.nw >$*.c .nw.o: $(NOTANGLE) -L $*.nw >$*.c $(CC) $(CFLAGS) -c $*.c .nw.h: $(NOTANGLE) -Rheader $*.nw $(CPIF) $*.h .tex.dvi: latex $* #---------------------------------------------------------------------- # all: prettytest: $(NWPPOBJS) $(NWPRETZELPPOBJS) $(NWPRETZELTESTOBJS) $(NWPPMAINOBJ) $(CC) $(NWPPOBJS) $(NWPRETZELPPOBJS) $(NWPRETZELTESTOBJS) \ $(NWPPMAINOBJ) $(CFLAGS) -o prettytest # use pretzel, flex and Bison to build objects for the test language # (use languages/pascal/Makefile as a reference for your own Makefiles # for Pretzel). Don't use pretzel-it because pretzel-it uses released # objects and we possibly want to link the non-released objects in # this directory. $(NWPRETZELTESTOBJS): $(TESTLANG).ft $(TESTLANG).fg pretzel $(TESTLANG) bison -d $(TESTLANG).y mv $(TESTLANG).tab.h ptokdefs.h flex -t $(TESTLANG).l > $(TESTLANG).lex.c $(CC) $(CFLAGS) -c $(TESTLANG).tab.c $(TESTLANG).lex.c source: $(SRCS) clean: rm -f *.tex *.log *.dvi *.o *.toc *.aux clobber: clean rm -f $(SRCS) rm -f prettytest ptokdefs.h $(TESTLANG).l $(TESTLANG).y \ $(TESTLANG).lex.c $(TESTLANG).tab.c # copy pretty.o as nowebpretzelpp.o to pretzel library directory and # add necessary objects to pretzel library release: $(NWPRETZELPPOBJS) $(NWPPOBJS) $(NWPPMAINOBJ) cp $(NWPPMAINOBJ) ../../../nowebpretzelpp.o ar vrus ../../../libpretzel.a $(NWPPOBJS) $(NWPRETZELPPOBJS) # test the resulting prettytest filter regression: prettytest noweave -delay -filter prettytest -index testcode.nw > testcode.tex latex testcode.tex latex testcode.tex #---------------------------------------------------------------------- # dependencies columns.o: columns.h errors.o: errors.h getline.o: columns.h errors.h getline.h match.o: match.h pretty.o: getline.h match.h errors.h pretty.h strsave.h strsave.o: strsave.h errors.h nowebpretzelpp.o: pretty.h pretzel-2.0n-2/contrib/noweb/general/test.ft0000644000000000000000000000035306635711136017565 0ustar rootroot/* this is a test formatted token file for a dumb prettyprinter. */ %% ; SEMI [a-zA-Z][a-zA-Z0-9]* ID_TYPE // identifiers [\t\ \n] // eat up whitespace . // eat up other non matching characters pretzel-2.0n-2/contrib/noweb/general/columns.nw0000644000000000000000000000313406255317024020275 0ustar rootroot% Copyright 1991 by Norman Ramsey. All rights reserved. % See file COPYRIGHT for more information. \subsection{Managing indentation and columns} These functions are used to help accumulate indentations across module boundaries by measuring the widths of various strings in columns. The size of things depends on [[tabsize]] as defined in columns.h. If [[tabsize == 0]], tabs shouldn't be touched on input and won't be generated on output. <
>= extern int tabsize; extern int columnwidth (char *s); /* number of columns string occupies */ extern int limitcolumn (char *s, int startcolumn); /* width of startcolumn blanks plus s */ extern void indent_for (int width, FILE *fp); /* indent to width; next char -> width+1 */ @ %def tabsize <<*>>= #include #include "columns.h" int tabsize = 8; <<*>>= int columnwidth (char *s) { /* width of a string in columns */ return limitcolumn(s, 0); } @ %def columnwidth <<*>>= int limitcolumn (char *s, int col) { while (*s) { col++; if (*s=='\t' && tabsize > 0) while (col % tabsize != 0) col++; s++; } return col; } @ %def limitcolumn <<*>>= void indent_for (int width, FILE *fp) { /* write whitespace [[width]] columns wide */ /*fprintf(fp,"<%2d>",width); if (width>4) {fprintf(fp," "); width -= 4;}*/ if (tabsize > 1) while (width >= tabsize) { putc('\t', fp); width -= tabsize; } while (width > 0) { putc(' ', fp); width--; } } @ %def indent_for pretzel-2.0n-2/contrib/noweb/index.html0000644000000000000000000000202406360666412016631 0ustar rootroot Index file for directory "pretzel/contrib/noweb" of Pretzel distribution

Index file for directory "pretzel/contrib/noweb" of Pretzel distribution

Files and directories are:

this directory

    noweb prettyprinters for Pretzel by Felix Gaertner
cee.html
    Test of C with HTML as back end
cee.latex
    rudimentary C with LaTeX as target
general
    general stuff for interfacing with noweb
java.latex
    good Java prettyprinter that also does indexing

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 12:50:51 MESZ 1997 pretzel-2.0n-2/diary-1.10000644000000000000000000002012206156051346013406 0ustar rootroot ----- Diary of the `pretzel' ----- It's Tuesday, 4th October 1994, and I am finally staring to work on this project again. There has been a break of over a year now between the last keys I added to this project and much has happened inbetween. I had started this project without having much experience in building things alike and this might be the key reason why reading the source code to this project strikes me with such severity. I am tempted to go over the code fully again and build everything from scratch. But having only one month left to finish it (own deadline) this doesn't seem feasible. Instead I will take the existing code as a frame and recycle most of the parts that have worked already. (This seems to be a good test to the LitProg style I've used a year ago.) Joachim is surely looking forward to putting an end to this project too, so I'll try to be as swift as possible. Anyway, I've done more complicated things and they've worked... Simplicity is the key for a fast final finish. Things to do: o Get rid of the `makeWEAVE' name and think of better terms for the `preBISON' and `preFLEX' files. o Strip off unessential code from the main program. Simplify the options. o Look at each of the file processors individually... Work will continue. We'll talk again on Monday, 31st October. 4-10-94: I'll use RCS to try and have the changes in style traceable. 5-10-94: Went to the library today and found the names I was looking for. The system will be called `pretzel' (which was the word following `pretty' in the dictionary). The `preFLEX' file will be the `token format' or `formatted token' file (or `token' file for short). The `preBISON' file will be the `grammar format' file or `formatted grammar' file. Starting to revise the code for the output class today. Stuffed everything into RCS. 6-10-94: Finished revision of specifications for the output class. Took me nearly 3 hours. Excluded the written history from the file. 7-10-94: Finished revision of the output class implementation. Wrote a small test program that shows that the standard stuff works nicely. This took me 2:30 hrs. Renamed fwmac.sty into pretzel.sty and stuffed it into RCS. 13-10-94: Had a few days off. It's hard to get back into it again. Finished the first revision of the specs for the Attribute class. (2:00) 14-10-94: Finished revision of the implementation of the attribute class. Added a picture and wrote the tester for it. (2:00) Renamed the following files and directories: preflex ftokens prebison fgrammar l_parse.spz ftparse.spc l_parse.y ftparse.y l_scan.spz ftscan.spc l_scan.y ftscan.y lwvtoken.h ftokdefs.h tl_parse ftokens Stuffed the whole freshly named set of ex-preflex files into RCS. 17-10-94: Revised formatted token scanner. Need to think about what to include in the specs for these modules. (1:30) 18-10-94: Changed the interface for the formatted token file parser. Now it is simply a generator for a prettyprinting scanner. The fact that it is a parser is shielded from the user. That's it: The ideas of this morning are quite convincing. This is they way I'll structure the program: Pretzel is a program that generates a prettyprinter from a formatted token file and a formatted grammar file. The prettyprinting method used is a parser using format command primitives. Pretzel can be divided into two parts: 1. The prettyprinting scanner. 2. The prettyprinting parser (the `real' prettyprinter). There are two functions/commands to build both parts: 1. ftokens (or the build_pscan() function). 2. fgrammar (or the build pparse() function). The first is a generator for the prettyprinting scanner and the second generates the prettyprinting parser. This is the general idea. There are ways to fine tune both the generated scanner and the parser (e.g. change the names of the generated functions). The way to change the name of the generated scanner is to redefine the macro PSCAN_NAME in the definitions section of the formatted token file (has to be bracketed with %{ and %}). Fine tuned the scanner generator today. It even does some error control now. (1:30) The thing to do now is to work on the parser generator. I'll do some preliminary work today and go on tomorrow. Next things to do would be to rewrite the specs and the implementation. I can go along the example tested with the scanner generator. But that's tomorrow. 19-10-94: New names: y_parse.spz fgparse.spc y_parse.y fgparse.y y_scan.spz fgscan.spc y_scan.l fgscan.l ywvtoken.h fgramdefs.h Function names changed too (e.g. y_parse -> build_pparse, etc.). Finished fgscanner and fgparser. I have to think about how to generate the header files for both. Now at least you can redefine the names of the generated scanner and parser, but the prettyprinting code inside the generated parser still uses intrisicts of the scanner. 20-10-94: Header files are not generated! This is a decision for simplicity. The user can write his own header files if he wants, because the interface of the generated scanner is well defined. It consists of two functions: int (Attribute** ); void _init (istream* ); where defaults to `pscan' but can be changed by redefining the PSCAN_NAME macro in the definitions section of the formatted token file. The scanner expects to find token code definitions (MATH, EXPR, ...) in a file called `ptokdefs.h' that has to be provided by the user. The name of the file can be changed by redefining PTOKDEFS_NAME. The generated parser also has a well defined interface. It consists of one function void (istream*, ostream*); where is the value of PPARSE_NAME or `pparse' by default. It expects a scanner (with the same specs as above) to be reachable as `pscan' and an initializer function as `pscan_init'. The name (prefix) of the scanner (and initializer) can be changed by redefining PSCAN_NAME at the beginning of the formatted grammar file. The parser expects a token header file under the name of `ptokdefs.h' to be in the current directory. The name can be changed by redefining PTOKDEFS_NAME. By default, the parser uses the generated scanner without change. 21-10-94: Now you can define the name of the scanner initialiser function seperately from the scanner name in both formatted token and grammar file. Also, as the generated parser doesn't need to include the common token definitions, he doesn't do it. Only the generated scanner does it (correctly now). In the generated scanner code there is a default version of the necessary yywrap() routine. If you want to declare a routine of your own you have to #undef PSCAN_YYWRAP in the definitions section of the formatted token file and supply a version of your own. 24-10-94: Added pscan.spc, a CWEB header template for the default prettyprinting scanner. Also added pparse.spc, a header template for the prettyprinting parser. Now pretzel works. There had been problems, because multiple main() programs had been included in the run time library, but after going over each individual Makefile this has been taken care of. Started to revise the documentation. Need to produce a user's manual quickly (a usable one). 25-10-94: Started to revise the second chapter, which is the main part of the user's manual. 27-10-94: Second chapter is half revised. 24-2-95: Spent the last week revising chapter 1. This week was spent in fine tuning the report. Today -- at last -- I'm finished and can hand it in. At least now I can be proud of it (a bit). 26-4-95: Today I finally gave the printed and bound version of the report to Joachim. That's that. Today I also met the first user of pretzel (apart from me, I've met me before). So I cleaned up the source code and bundled everything together nicely. 27-4-95: Another printout for other people interested in pretzel. Together with the GNU GPL it's ready for the ftp server. That's that. Final remarks will be added to the README. Changes will be documented in the change logs of the files. --------------------------------------------------------------------- pretzel-2.0n-2/debian/0000755000000000000000000000000010765026553013306 5ustar rootrootpretzel-2.0n-2/debian/changelog0000644000000000000000000000240710765021023015146 0ustar rootrootpretzel (2.0n-2-0.3) unstable; urgency=medium * Non-maintainer upload. * Fix FTBFS with GCC 4.3 (Closes: #461686). -- Luk Claes Sun, 09 Mar 2008 17:44:25 +0000 pretzel (2.0n-2-0.2) unstable; urgency=low * NMU * debian/rules: Fix bashism. (Closes: #459169) -- Marc 'HE' Brockschmidt Tue, 22 Jan 2008 22:05:06 +0100 pretzel (2.0n-2-0.1) unstable; urgency=low * NMU during Darmstadt BSP. * Fix FTBFS. Closes: #266037. -- Andreas Barth Sat, 21 Aug 2004 19:12:14 +0200 pretzel (2.0n-2) unstable; urgency=low * Updated to modern C++ string standards. Thanks to LaMont Jones for the patch. (Closes: Bug#196579) * Removed reference to dh_suidregister. * Include everything in contrib in doc/examples/contrib. (Closes: Bug#74596) -- Anthony Towns Fri, 22 Aug 2003 03:25:37 +1000 pretzel (2.0n-1.1) unstable; urgency=low * Non-maintainer upload. * debian/control (Build-Depends): add debhelper, closes: #109646. * debian/changelog: remove local variables stuff. -- James Troup Wed, 22 Aug 2001 17:33:18 +0100 pretzel (2.0n-1) unstable; urgency=low * Initial Release. -- Anthony Towns Sun, 7 May 2000 23:24:38 +1000 pretzel-2.0n-2/debian/copyright0000644000000000000000000000216110111701037015217 0ustar rootrootThis package was debianized by Anthony Towns on Wed, 20 May 1998 18:59:40 +1000. It was downloaded from http://www.iti.informatik.tu-darmstadt.de/~gaertner/pretzel/code Copyright: This is Pretzel v.2.0, the language independent prettyprinter generator. Copyright (C) 1997 by Felix Gaertner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. On Debian systems, a copy of the GPL is available as /usr/share/common-licenses/GPL . pretzel-2.0n-2/debian/rules0000755000000000000000000000525510765026540014371 0ustar rootroot#!/usr/bin/make -f # MAde with the aid of dh_make, by Craig Small # Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. # Some lines taken from debmake, by Cristoph Lameter. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 build: build-stamp build-stamp: dh_testdir # Add here commands to compile the package. $(MAKE) CFLAGS="-O2 -g -Wall -W -I`pwd`/include -L`pwd` -lpretzel" touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp # Add here commands to clean up after the build process. $(MAKE) clobber rm -rf tmpcee tmppascal rm -f contrib/noweb/general/testpp dh_clean # Build architecture-independent files here. binary-indep: build # We have nothing to do by default. DST := $(PWD)/debian/tmp # Build architecture-dependent files here. binary-arch: build # dh_testversion dh_testdir dh_testroot dh_clean -k dh_installdirs # Add here commands to install the files into debian/tmp $(MAKE) install DESTDIR=`pwd`/debian/tmp cp doc/pretzelbook/pretzelbook.dvi debian/tmp/usr/share/doc/pretzel/ mkdir -p $(DST)/usr/share/doc/pretzel/examples/simpas cp -a languages/examples $(DST)/usr/share/doc/pretzel/examples/simpas cp -a languages/cee $(DST)/usr/share/doc/pretzel/examples/ cp -a languages/cplusplus $(DST)/usr/share/doc/pretzel/examples/ cp -a languages/pascal $(DST)/usr/share/doc/pretzel/examples/ mkdir $(DST)/usr/share/doc/pretzel/examples/contrib cp -r contrib/* $(DST)/usr/share/doc/pretzel/examples/contrib/ rm -f debian/tmp/usr/share/doc/pretzel/examples/*/index.html debian/tmp/usr/share/doc/pretzel/examples/*/index.list # for a in cee pascal; do \ # mkdir tmp$$a; cd tmp$$a; \ # cp ../debian/tmp/usr/share/doc/pretzel/examples/$${a}/* .; \ # PATH=$$PATH:../debian/tmp/usr/bin PRETZEL_LIBDIR=../debian/tmp/usr/lib/pretzel PRETZEL_INCLUDE=../debian/tmp/usr/include/pretzel ../pretzel-it/pretzel-it $${a} $${a}pp; \ # PATH=$$PATH:../debian/tmp/usr/bin PRETZEL_LIBDIR=../debian/tmp/usr/lib/pretzel PRETZEL_INCLUDE=../debian/tmp/usr/include/pretzel ../pretzel-it/pretzel-it -n $${a} pretty$${a}; \ # mv $${a}pp pretty$${a} ../debian/tmp/usr/bin/ ;\ # cd ..; rm -rf tmp$$a; \ # done dh_installdocs dh_installexamples dh_installmenu # dh_installinit dh_installcron dh_installmanpages # dh_undocumented dh_installchangelogs diary diary-1.1 dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol # dh_makeshlibs dh_md5sums dh_builddeb source diff: @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary pretzel-2.0n-2/debian/docs0000644000000000000000000000003406537750101014151 0ustar rootrootREADME TODO diary diary-1.1 pretzel-2.0n-2/debian/control0000644000000000000000000000136310111701037014672 0ustar rootrootSource: pretzel Section: devel Priority: extra Maintainer: Anthony Towns Standards-Version: 3.1.1 Build-Depends: nowebm, flex (>= 2.4.6), bison (>= 1.19), debhelper Package: pretzel Architecture: any Depends: ${shlibs:Depends}, flex (>= 2.4.6), bison (>= 1.19) Recommends: noweb | nowebm Description: Prettyprinter generator for noweb Pretzel is a system that builds prettyprinters; that is programs that will take some plain ASCII source code and generate a LaTeXified version for presentation. . Pretzel has hooks to integrate with noweb, so that code chunks may be prettyprinted with pretzel's generated prettyprinters. . Example prettyprinter source for C, C++, Pascal, and Dijkstra's Guarded Command Language are included. pretzel-2.0n-2/debian/postinst0000644000000000000000000000024210111701037015070 0ustar rootroot#!/bin/sh set -e if [ "$1" = "configure" ]; then if [ -x /usr/bin/texhash ]; then /usr/bin/texhash >/dev/null fi fi ##DEBHELPER## pretzel-2.0n-2/debian/postrm0000644000000000000000000000020610111701037014531 0ustar rootroot#!/bin/sh set -e if [ "$1" = "remove" ]; then if [ -x /usr/bin/texhash ]; then /usr/bin/texhash >/dev/null fi fi ##DEBHELPER## pretzel-2.0n-2/debian/dirs0000644000000000000000000000022610765026547014175 0ustar rootrootusr/bin usr/lib/pretzel usr/share/texmf/tex/latex/pretzel usr/share/man/man1 usr/include/pretzel usr/share/doc/pretzel usr/share/doc/pretzel/examples pretzel-2.0n-2/main/0000755000000000000000000000000010765026553013010 5ustar rootrootpretzel-2.0n-2/main/pretzel.nw0000644000000000000000000006601010765025446015046 0ustar rootroot% This is a file written using noweb % % $Id: pretzel.nw,v 1.2 1996/09/02 16:21:23 gaertner Exp gaertner $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{{Pretzel -- The Program\\} \vskip5pt\normalsize Version 2.0} \author{Felix G\"artner} \maketitle \begin{abstract} This document describes the implementation of pretzel, the universal prettyprinter generator. \end{abstract} \tableofcontents \section{Introduction} Do literate programming tools need to do prettyprinting? This is a question much discussed not only in the academic community. As a result of this discussion such tools can be divided into those that do prettyprinting and those that don't. Those people that like a nicely formatted source code however don't always have the same taste concerning formatting and so it is a great drawback that the majority of literate programming tools has the style of prettyprinting `hard wired' into the system itself and is (to be nice) very inflexible. This paper describes the main program of the ``pretzel'' project. The this project is an attempt to encapsulate the problems of prettyprinting and allow future tools to be simpler and more flexible, because they can concentrate on other important features and mustn't waste their energy on the intricate details of prettyprinting. In short: pretzel is a prettyprinter generator. The concept of pretzel is visualized in figure \ref{concept-fig}. It takes a formal specification of how a given language should be prettyprinted as input and produces a prettyprinter that behaves as specified. \begin{figure}[h] \begin{center} \setlength{\unitlength}{0.012500in}% \begin{picture}(42,69)(57,735) \put( 57,795){\makebox(0,0)[lb]{formal description}} \thinlines \put( 90,786){\vector( 0,-1){ 36}} \put( 63,735){\makebox(0,0)[lb]{prettyprinter}} \put( 99,765){\makebox(0,0)[lb]{pretzel}} \end{picture} \end{center} \caption{The concept of pretzel.} \label{concept-fig} \end{figure} The way in which the ``style'' of prettyprinting is defined is closely related to the prettyprinting method used by the generated prettyprinter. The main idea of this method is that the source code is parsed and enhanced with formatting instructions for a typesetter. The actual typesetting is then done by a typesetter program. For a detailed description see the main documentation of this project. The formal definitions of the prettyprinting ``style'' have to be supplied by the user in two files: % \begin{itemize} \item a formatted token file (with suffix {\tt .ft}) and \item a formatted grammar file (with suffix {\tt .fg}). \end{itemize} % In short, the formatted token file contains the way in which each individual language token is formatted. It defines such things as printing reserved words in bold face or how to typeset individual symbols. The formatted grammar file on the other hand defines the more global format, e.g.~indentation or line breaks. For more information and a complete example again see the main documentation of this project. Figure \ref{detailed-concept} shows a more detailed view of the way in which pretzel works. Because the resulting prettyprinter works using a parser, we have to supply both a parser and a scanner. These two parts of the prettyprinter will be called the {\em prettyprinting scanner} and the {\em prettyprinting parser}. Pretzel doesn't create these parts directly, but produces source for scanner and parser generators. In this version the generated code is compliant to the standard GNU tools {\em flex} and {\em Bison}. \begin{figure} \begin{center} \setlength{\unitlength}{0.012500in}% \begin{picture}(119,169)(13,648) \thinlines \put(102,792){\vector( 0,-1){ 27}} \put( 36,747){\vector( 0,-1){ 30}} \put(105,747){\vector( 0,-1){ 27}} \put( 36,687){\line( 0,-1){ 12}} \put( 36,675){\line( 1, 0){ 30}} \put( 66,675){\vector( 0,-1){ 12}} \put(105,684){\line( 0,-1){ 9}} \put(105,675){\line(-1, 0){ 30}} \put( 75,675){\vector( 0,-1){ 12}} \put( 39,810){\makebox(0,0)[b]{formatted }} \put( 39,795){\makebox(0,0)[b]{token file}} \put(105,810){\makebox(0,0)[b]{formatted}} \put(105,795){\makebox(0,0)[b]{grammar file}} \put( 36,789){\vector( 0,-1){ 24}} \put( 36,753){\makebox(0,0)[b]{flex source}} \put( 72,678){\makebox(0,0)[b]{CC}} \put(105,753){\makebox(0,0)[b]{Bison source}} \put( 33,705){\makebox(0,0)[b]{C code}} \put( 33,690){\makebox(0,0)[b]{(scanner)}} \put(105,705){\makebox(0,0)[b]{C code}} \put(105,690){\makebox(0,0)[b]{(parser)}} \put( 72,648){\makebox(0,0)[b]{pparse(istream*, ostream*)}} \put( 69,774){\makebox(0,0)[b]{pretzel}} \put( 72,732){\makebox(0,0)[b]{flex / Bison}} \end{picture} \end{center} \caption{A more detailed overview over the concept of pretzel.} \label{detailed-concept} \end{figure} Together with these tools you can generate the \C\ code for a new \CPP\ prettyprinter class that looks somewhat like this: % \begin{verbatim} class Pparse { // abstract base class public: Pparse(); ~Pparse(); virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*, ostream*) = 0; }; class PPARSE_NAME : public Pparse { PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*, ostream*); void debug_on(); void debug_off(); }; \end{verbatim} % The name [[PPARSE_NAME]] can be redefined by the user and defaults to [[Ppparse]]. \paragraph{Naming conventions:} Pretzel expects the two input files to have the {\tt .ft} and {\tt .fg} suffixes. The generated scanner and parser sources will have the same prefix, but the suffixes are replaced by {\tt .l} (scanner) and {\tt .y} (parser). Both generated files are self contained entities, i.e.~they can be used seperately for different purposes. \paragraph{Command line options:} We want to allow the following options and command line parameters: \begin{description} \item[options:]\hfill\par \begin{itemize} \item \t{-q}\quad run quietly (no screen messages will be output) \item \t{-t}\quad process formatted token file only \item \t{-g}\quad process formatted grammar file \item \t{-d}\quad debug mode (see section below) \item \t{-h}\quad show full usage (help) \item \t{-o name}\quad names of the output files begin with \t{name} \end{itemize} \item[parameters:]\hfill\par \begin{itemize} \item \t{name1}\quad prefix of the two input files (suffixes \t{.ft} and \t{.fg} will be assumed); meaning of this parameter changes if the following parameter is given \item \t{name2}\quad name of the formatted grammar file; if this name is given, the parameter \t{file1} is the name of the formatted token file \end{itemize} \end{description} Thus, we end up with the following usage: \begin{center} \tt pretzel [-qtgdh] [-o outfile] (prefix $\vert$ file1 file2) \end{center} The options \t{-t} and \t{-g} are mutually exclusive, i.e.~you can't choose both at the same time. The other options are tackled from left to right. @ This is an overview of the entire program. The named sections will be filled up step by step in the course of this text. <>= <

> <> <> <> <> @ The following line is printed out every time pretzel is run. <>= #define banner "This is pretzel, version 2.0." @ Here's a first set of header files that we'll surely need. Others will be included later. <
>= #include #include using namespace std; @ And since some (really old) operating systems don't have the common [[EXIT_FAILURE]] and [[EXIT_SUCCESS]] macros defined (in [[stdlib.h]]), we'll define them here. <
>= #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif @ @ Pretzel will have a debug option at the command line. If you use the \t{-d} option the program will print out to the screen several lines of text about what it is doing. To indicate if we're in debug mode, I'll have a global variable [[mode]] that can either hold [[debug]] or [[normal]] values. <>= #define normal 0 #define debug 1 @ During program development I will use a macro [[PRETZEL_DEBUG]] for the same purpose. If this macro is defined the program will run as if the \t{-d} option has been set. I chose this tactic to test the code that analyses the options. <>= #ifdef PRETZEL_DEBUG int mode = debug; #else int mode = normal; #endif @ To print out debug messages I'll use a function called [[debug_message]] that takes a string and outputs it to the standard error stream if we're debugging. A newline character is automatically added. <>= void debug_message ( char* s ) { if (mode == debug) { cerr << s << endl; } return; } @ Finally, you might ask: Why calling a system like this ``pretzel''? To be honest, I had severe problems in finding something appropriate, but looking at my dictionary I had an idea! The system here is a generator for prettyprinters, i.e.~it is more than a prettyprinter. Looking for more about the word ``pretty'' I came across ``pretzel'', which was the word that immediately followed it (at least in my dictionary). \section{The plan of the program} The plan of attack is very simple: This program has to process the two given files from the beginning and turn them into valid flex and Bison files. We want to accept command line parameters as stated above. The [[main]] program is easily stated. Note that we have to output the banner line after we've processed the command line, because the user might have used the {\tt -q} option. <>= int main( int argc, char *argv[] ) { <> debug_message("Starting the main program..."); <> <> <> <> <> debug_message("Ending gracefully..."); return(EXIT_SUCCESS); } @ If we encounter a fatal error, we'll simply output a short message and quit. <>= void fatal_error( char* s ) { cerr << "fatal error: " << s << endl; exit(EXIT_FAILURE); } @ \section{Processing the command line} In the introduction I've given an oveview over the options that pretzel has. Which of the command line arguments are used is stored in the following [[int]] variables. The option is either [[ON]] or [[OFF]]. All options are [[OFF]] initially. The debug option is an exception here, because it is handled by the global [[mode]] variable and because it might be on initially due to the [[PRETZEL_DEBUG]] macro. <>= #define ON 0 #define OFF 1 @ Table \ref{tab:optvars} shows the variables and the associated meaning they carry. \begin{table} \begin{center} \begin{tabular}{IlIlI} \hline variable & option \\ \hline [[be_quiet]] & \tt -q \\ [[ft_only]] & \tt -t \\ [[fg_only]] & \tt -g \\ [[full_usage]] & \tt -h \\ \hline \end{tabular} \end{center} \caption{Variables that store options.} \label{tab:optvars} \end{table} <>= int be_quiet = OFF; int ft_only = OFF; /* want to have both files by default */ int fg_only = OFF; int full_usage = OFF; @ Now that we know about [[be_quiet]], we can tell the program to output the banner line only if wanted. <>= if (be_quiet==OFF) { cout << banner << endl; } @ Saying bye bye is similar. <>= if (be_quiet==OFF) { cout << "No errors found." << endl; } @ Now we turn to the names of the input files. There are at most two input files: % \begin{enumerate} \item the formatted token file and \item the formatted grammar file. \end{enumerate} % The names of these input files are stored in the variables [[ft_filename]] and [[fg_filename]]. <>= #define MAX_STRING_LENGTH 100 @ <>= char ft_filename [ MAX_STRING_LENGTH ]; char fg_filename [ MAX_STRING_LENGTH ]; @ Now we turn to the output files. The output files are in analogy to the input files % \begin{enumerate} \item the scanner source file and \item the parser source file. \end{enumerate} % The names of the output files are stored in the follwing two variables. Their names will be pieced together at run time. <>= char scanner_filename [ MAX_STRING_LENGTH ]; char parser_filename [ MAX_STRING_LENGTH ]; @ If the {\tt -o} option is used we need a place to store this prefix. This will be done in the global [[outfile_prefix]]. It's important that it is initialised to the empty string because this will be used as an indication whether the {\tt -o} option has been used or not. <>= char outfile_prefix [ MAX_STRING_LENGTH ] = ""; @ Now that we have discussed the names of the files, we will meet these files in person. Input comes from two input file streams [[ft_file]] and [[fg_file]]. <>= ifstream ft_file; ifstream fg_file; @ Output goes to these two output file streams. <>= ofstream scanner_file; ofstream parser_file; @ We need the {\tt fstream.h} header to do this. <
>= #include using namespace std; @ Of course not all of the input and output streams are really used during every run of the program. For instance there will be no need of [[ft_file]] if the \t{-g} (process only formatted grammar file) option is used. \subsection{Getting the options} Now we come to the tricky part where the command line options are investigated. To analyse the command line options we will use the [[getopt]] subroutine from the following library. <
>= #include @ These variables will be used by [[getopt]]. <>= extern int optind; extern char *optarg; extern int opterr; @ The [[opterr]] variable must be set to 0 because we don't want [[getopt]] to issue error messages. <>= opterr=0; /* don't let [[getopt]] issue error messages */ @ The following code analyses the options. If the given options are confusing a message about correct usage will be output on the screen. The [[errorflag]] variable is used to check this. The extra pair of brackets limit the scope of the [[errorflag]]. <>= { int errorflag = OFF; debug_message("Starting to analyse the command line..."); <> <> <> <> if (errorflag==ON) { <> } debug_message("Command line options and parameters okay!"); } /* get rid of the errorflag */ @ Here we are now looking at the {\em command line options} first. The extra brackets are used to eliminate the character [[c]]. <>= { int c; /* used to store the character returned by [[getopt]] */ debug_message("Beginning to analyse the command line options..."); while (( c = getopt(argc, argv, "qtgdho:") ) != EOF) { switch (c) { <> default: debug_message("Unknown option"); errorflag=ON; /* this case also for `?' */ } /* switch */ } /* while */ } /* get rid of [[c]] */ @ The command line options are handled from left to right. The debug option {\tt -d} overrides the quiet option {\tt -q}, i.e.~if both are given, pretzel prints out debug messages, but doesn't print normal stuff, like the banner line. Only if {-q} is given on its own, pretzel won't output anything. So first let's have a look at the options that can change the path of the output. The simplest one is probably {\tt -q}. The \t{-q} option turns off all regular output. <>= case 'q': be_quiet = ON; break; @ The {\tt -d} option sets the mode to [[debug]]. This causes pretzel to output debug messages during its run. (If you want to debug the processing of the command line options, you must compile this program with the [[PRETZEL_DEBUG]] macro defined. Then the [[mode]] is set to [[debug]] when it is declared.) <>= case 'd': mode = debug; break; @ The {\tt -o} option defines the prefix of the output files. We'll simply copy the string given on the command line to our [[outfile_prefix]] storage. <>= case 'o': strncpy(outfile_prefix,optarg, MAX_STRING_LENGTH); outfile_prefix[MAX_STRING_LENGTH -1] = '\0'; break; @ For these cases we need the header file that copes with strings. <
>= #include @ The \t{-t} and \t{-g} options turn on their corresponding option tags. Care is taken that not both are on at the same time. <>= case 't': if (fg_only==ON) errorflag = ON; else ft_only=ON; break; case 'g': if (ft_only==ON) errorflag = ON; else fg_only=ON; break; @ Finally we have to record whether the user wanted to see the full usage. <>= case 'h': full_usage=ON; break; @ Now we can handle the command line parameters. We can have at most two of them. The meaning of the first parameter depends on the actual number of parameters. If there is only one parameter given, it specifies the prefix of both formatted token and grammar file. If two parameters are given, the first is the name of the formatted token and the second is the name of the formatted grammar file. The value of [[argc]] is the number of parameters (including options) plus one. [[optind]] is an index into [[argv]] and specifies which string will be processed next. At this point of the program there are only two possible correct situations: % \begin{enumerate} \item Either there is only one parameter left in [[argv]] and thus [[optind]]=[[argc-1]], \item or there are still two parameters left; this is described by [[optind]]=[[argc-2]]. \end{enumerate} % If a correct number of parameters is left in [[argv]] the following precondition for this code fragment must hold: \begin{center} [[argc-2]] $\leq$ [[optind]] $\leq$ [[argc-1]] \end{center} <>= debug_message("Beginning to analyse the parameters..."); if (!( ( argc-2<= optind) && (optind <=argc-1) )) { debug_message("Wrong number of parameters!"); errorflag=ON; } else { /* we have a correct number (one ore two) parameters */ if (optind==argc-1) { debug_message("One command line parameter"); <> } else { debug_message("Two command line parameters"); <> } } @ If only one parameter is given, this name defines the beginning of the output files. Any suffix is ignored, so don't mention {\tt .ft} or {\tt .fg} to pretzel. <>= #define ft_suffix ".ft" #define fg_suffix ".fg" @ <>= strncpy(ft_filename, argv[argc-1], MAX_STRING_LENGTH); strcat(ft_filename, ft_suffix ); strncpy(fg_filename, argv[argc-1], MAX_STRING_LENGTH); strcat(fg_filename, fg_suffix ); @ If two parameters are given we assume that they contain the full filenames. <>= strncpy(ft_filename, argv[argc-2], MAX_STRING_LENGTH); strncpy(fg_filename, argv[argc-1], MAX_STRING_LENGTH); @ The names of the output files are computed from the [[outfile_prefix]] (if any) and the extensions \t{.l} for the scanner file and \t{.y} for the parser file. If no outfile prefix was given, the prefixes of the individual files are taken. If only one file was specified and we haven't seen the {\tt -o} option, we'll take the full name and ignore any suffixes that it may have. <>= if (strlen(outfile_prefix) == 0) { strncpy(outfile_prefix, argv[argc-1], MAX_STRING_LENGTH); } @ If two names were given, we cut off possible standard suffixes and take the remaining string as prefix. I'm not going to do this code here \ldots [XXX] <>= #define default_prefix "default.pp" @ <>= if (strlen(outfile_prefix) == 0) { strncpy(outfile_prefix, default_prefix, MAX_STRING_LENGTH); } @ The output file names are now pieced together. <>= #define scanner_suffix ".l" #define parser_suffix ".y" @ <>= strncpy(scanner_filename, outfile_prefix, MAX_STRING_LENGTH); strcat(scanner_filename, scanner_suffix); strncpy(parser_filename, outfile_prefix, MAX_STRING_LENGTH); strcat(parser_filename, parser_suffix); @ This text will always be output if an error is discorvered during analysis of the command line. If the \t{-h} option was used the message will be a little longer than normal. <>= cerr << banner << endl << "Usage: " << argv[0] << " [-qtgdh] [-o outfile] (prefix | file1 file2)" << endl; <> exit(EXIT_FAILURE); @ Here is the full notice. <>= if (full_usage==ON) { cerr << "Options:" << endl << " -q run quietly" << endl << " -t process formatted token file only" << endl << " -g process formatted grammat file only" << endl << " (options -t and -g are mutually exclusive)" << endl << " -d print debug information to the screen" << endl << " -h print full usage (help)" << endl << " -o name output files begin with `name'" << endl << "Parameters:" << endl << " prefix prefix of the input file names (extensions" << endl << " `.ft' and `.fg' are assumed)" << endl << " file1 full name of the formatted token file" << endl << " file2 full name of the formatted grammar file" << endl << endl; } else { cerr << "Say `" << argv[0] << " -h' for full usage." << endl; } @ If we are debugging we want to check that the program has analysed the options correctly. We use the following macro to shorten the code. <>= #define display_status(option) { \ if (option==ON) cerr << "ON" << endl; \ else cerr << "OFF" << endl; \ } @ The options will only be output if we are debugging. <>= if (mode == debug) { <> } @ This code prints a nice table filled with information about command line otions and parameters. <>= cerr << "These are the chosen options:" << endl << " quiet (-q): "; display_status(be_quiet); cerr << " tokens only (-t): "; display_status(ft_only); cerr << " grammar only (-g): "; display_status(fg_only); cerr << " help (-h): "; display_status(full_usage); cerr << " outfile prefix: " << outfile_prefix << endl << " scanner file name: " << scanner_filename << endl << " parser file name: " << parser_filename << endl << "These are the specified parameters:" << endl << " name of token file: " << ft_filename << endl << "name of grammar file: " << fg_filename << endl; cerr << endl; @ \section{Processing the input files} Now we come to the main part of this program. Our aim is to mangle the input files in such a way that we end up with valid scanner and parser source files. The only thing to look out for if the user actually wants us to do the job. The actual work of generating the output files is done within two \CPP\ classes: % \begin{itemize} \item [[Pscan_builder]], that builds the prettyprinting scanner from a formatted token file (see {\tt ftparse.nw}) and \item [[Pparse_builder]], that builds a prettyprinting parser (see file {\tt fgparse.nw}. \end{itemize} % Both classes have a member function [[build]] that takes an input stream and an output stream pointer. They read from the input stream and write to the output stream. <
>= #include"ftparse.h" #include"fgparse.h" @ These are the two objects that we'll use to build the output files. <>= Pscan_builder scanner_generator; Pparse_builder parser_generator; @ The formatted token file is only processed if the [[fg_only]] tag is set off. <>= if (fg_only==OFF) { <> } @ If we aren't supposed to be quiet, we give an indication of what we're doing. <>= if (be_quiet == OFF) { cout << "Processing the formatted token file (" << ft_filename << " -> " << scanner_filename << ")." << endl; } @ First of all we have to open the two files and see if they are there. <>= ft_file.open(ft_filename); if (!ft_file) { fatal_error("Opening formatted token file failed."); } @ Then we have to open the scanner file for output. <>= scanner_file.open(scanner_filename); if (!scanner_file) { fatal_error("Opening scanner file failed."); } @ Next we'll call our handy routine that does the job for us. We have to check for errors though. <>= if (scanner_generator.build(&ft_file, &scanner_file) != 0) { cerr << scanner_generator.error_text() << " in line " << scanner_generator.error_line() << " of `" << ft_filename << "'." << endl; fatal_error("Exiting."); } @ We're sure to close the two files again. <>= ft_file.close(); scanner_file.close(); @ The processing of the formatted grammar file is nearly an exact copy of the above sections. The only things changed are the names of the files and the name of the generator function. <>= if (ft_only==OFF) { <> } @ Again, we'll say what we're doing. <>= if (be_quiet == OFF) { cout << "Processing the formatted grammar file (" << fg_filename << " -> " << parser_filename << ")." << endl; } @ First of all we have to open the two files again and see if they are there. <>= fg_file.open(fg_filename); if (!fg_file) { fatal_error("Opening formatted grammar file failed."); } @ Then we have to open the parser file for output. <>= parser_file.open(parser_filename); if (!parser_file) { fatal_error("Opening parser file failed."); } @ Next we'll call our handy routine that does the job for us. <>= if (parser_generator.build(&fg_file, &parser_file) != 0) { cerr << parser_generator.error_text() << " in line " << parser_generator.error_line() << " of `" << fg_filename << "'." << endl; fatal_error("Exiting."); } @ We're sure to close the two files again. <>= fg_file.close(); parser_file.close(); @ That's all folks. \end{document} % % $Log: pretzel.nw,v $ % Revision 1.2 1996/09/02 16:21:23 gaertner % Added missing #include % % Revision 1.1 1996/03/21 09:06:57 gaertner % Initial revision % % pretzel-2.0n-2/main/pascal.ft0000644000000000000000000000167105653202774014614 0ustar rootroot/* this is an example formatted token file for a pascal * prettyprinter. */ %% // with a little comment "<>" MATH { "$\\neq$" } "<=" | ">=" | ":=" MATH '[^'|'']*' SIMP "(" OPEN ")" CLOSE "[" OPEN "]" CLOSE "*" MATH "," MATH { ** + opt9 } ".." MATH "." SIMP ":" COLON ";" SEMI "=" MATH "+" MATH [0-9]+ SIMP [0-9]*"."[0-9]+ SIMP and MATH array ALPHA begin BEG {force + **} case ALPHA {force + **} const INTRO {force + backup + **} div MATH do OMEGA downto MATH else ELSE end END for ALPHA function PROC {force+backup+ **} if ALPHA { "{\\bf " + ** + "}" } mod MATH not MATH of OMEGA or MATH procedure | program PROC {force + backup + **} record BEG repeat BEG {force + ** } then OMEGA to MATH type INTRO {force + backup + **} until UNTIL {force + backup + **} var INTRO {force + backup + **} while ALPHA {force + **} [a-zA-Z][a-zA-Z0-9\_]* SIMP [\t\ \n] . %% /* here's some additional C code */ pretzel-2.0n-2/main/plainpp.c0000644000000000000000000000114210765025370014611 0ustar rootroot/* * $Id: plainpp.c,v 1.3 1996/03/21 11:05:24 gaertner Exp $ */ /* a minimal main program for the generated prettyprinter */ #include using namespace std; #include "Ppparse.h" int main () { Ppparse prettyprinter; prettyprinter.prettyprint(&cin,&cout); return(0); } /* * $Log: plainpp.c,v $ * Revision 1.3 1996/03/21 11:05:24 gaertner * Uses new interface to prettyprinter now. * * Revision 1.2 1996/03/21 09:15:13 gaertner * Version before switching to new interface of pretzel 2.0 * * Revision 1.1 1995/07/20 09:40:54 gaertner * Initial revision * * */ pretzel-2.0n-2/main/index.list0000644000000000000000000000060006360714217015005 0ustar rootrootthis directory & the main Pretzel program Makefile & the Makefile pascal.correct.l & correct outputs for regression test pascal.correct.y & pascal.fg & test input files pascal.ft & plaindpp.c & a minimal main program that uses the prettyprinter module (prettyprints in debug mode) plainpp.c & a minimal main program that is not in debug mode pretzel.nw & the noweb source of Pretzel pretzel-2.0n-2/main/index.html0000644000000000000000000000244606360714231015004 0ustar rootroot Index file for directory "pretzel/main" of Pretzel distribution

Index file for directory "pretzel/main" of Pretzel distribution

Files and directories are:

this directory

    the main Pretzel program
Makefile
    the Makefile
pascal.correct.l
    correct outputs for regression test
pascal.correct.y
pascal.fg
    test input files
pascal.ft
plaindpp.c
    a minimal main program that uses the prettyprinter module (prettyprints in debug mode)
plainpp.c
    a minimal main program that is not in debug mode
pretzel.nw
    the noweb source of Pretzel

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:56:42 MESZ 1997 pretzel-2.0n-2/main/plaindpp.c0000644000000000000000000000072710765025343014765 0ustar rootroot/* * $Id: plaindpp.c,v 1.1 1996/03/22 11:20:47 gaertner Exp $ */ /* a minimal main program for the generated prettyprinter * (this one turns the debugging features on by default) */ #include #include "Ppparse.h" int main () { Ppparse prettyprinter; prettyprinter.debug_on(); prettyprinter.prettyprint(&cin,&cout); return(0); } /* * $Log: plaindpp.c,v $ * Revision 1.1 1996/03/22 11:20:47 gaertner * Initial revision * * */ pretzel-2.0n-2/main/Makefile0000644000000000000000000001306306537746404014461 0ustar rootroot# $Id: Makefile,v 2.0 1996/12/16 17:33:16 gaertner Exp $ # ---------------------------------------------------------------------- # # Makefile for the main pretzel program and plainpp/plaindpp files # # this is the current version VERSION = 2.0 # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = g++ # de-comment this if you want a debug version: #DBVERSION = -D PRETZEL_DEBUG # compiler flags: CFLAGS = -g -I../include -L.. -lpretzel # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # You probably don't need to change anything from here: # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # Groups of files: # all noweb sources NOWEBS = pretzel.nw # root chunk name of headers HEADERCHUNK = header # root chunk name of implementation IMPLEMENTATIONCHUNK = implementation # all `WEB' sources (old) #WEBS = pretzel.w # all other program WEB sources (old) #ETCWEBS = # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = Makefile pascal.correct.l pascal.correct.y pascal.ft pascal.fg \ plainpp.c plaindpp.c # name of the distribution package #DISTNAME = main # Which program to make by default: PROG = pretzel # objects of this program: OBJS = pretzel.o # C sources of this program: CSRCES = pretzel.c # these objects should be created too: RELOBJS = plainpp.o plaindpp.o # all stuff to be removed too: OTHERCRAP = pretzel.tex pretzel.aux pretzel.idx pretzel.log \ pretzel.scn pretzel.toc pretzel.dvi \ pascal.l pascal.y # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) $(RELOBJS) # these are all header files produced from WEBs that may appear ALLHEADERS = # these are all the executables that could be produced ALLPROGS = $(PROG) # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle NOTANGLE= notangle NOWEAVE = noweave TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex -d #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = tex-it latex # ---------------------------------------------------------------------- .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h # overall rules: .nw.tex: $(NOWEAVE) -delay $*.nw > $*.tex .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .nw.h: $(NOTANGLE) -L -R$(HEADERCHUNK) $*.nw > $*.h .nw.c: $(NOTANGLE) -L -R$(IMPLEMENTATIONCHUNK) $*.nw > $*.c .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) $(CCFLAGS) -c $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) $(CC) -o $@ $(OBJECTS) $(CCFLAGS) $(OBJS): $(HEADERS) $(CSRCES) # list all source code: print: # apply lint to all C sources: lint: # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(OTHERCRAP) # remove everything that doesn't belong to original source: clobber: clean $(REMOVE) $(ALLPROGS) $(REMOVE) $(DISTNAME).tar # bundle source files together into an archive: #bundle: # tar cf $(DISTNAME).tar \ # $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # make a regression test: regression: $(PROG) ./pretzel pascal if { diff pascal.l pascal.correct.l && \ diff pascal.y pascal.correct.y; } \ then echo "Regression test is fine."; \ else echo "Regression test failed."; \ fi # copy executables into PATH directories, et al. release: $(PROG) $(RELOBJS) cp $(PROG) ../bin cp $(RELOBJS) .. # ====================================================================== # # $Log: Makefile,v $ # Revision 2.0 1996/12/16 17:33:16 gaertner # *** empty log message *** # # Revision 1.9 1996/09/12 18:40:05 gaertner # Changed CC to g++ and added $(PROG) to regression line. # # Revision 1.8 1996/03/22 11:21:36 gaertner # Uses noweb stuff now. # Added plaindpp.c/o parts. # # Revision 1.7 1995/09/07 17:36:59 gaertner # Changed target `install' to `release'. # # Revision 1.6 1995/04/26 16:47:09 gaertner # The .w.dvi implicit rule now uses Latex. # The used library is now lpretzel. # The binary is copied to ../bin instead of ../../bin (this # makes it more portable). # You can make a regression test with `make regression'. # `clean' now removes all stuff produced by regression and Latex'ing # of pretzel.w. # `clobber' also removes main.tar # # Revision 1.5 1994/10/31 19:06:06 gaertner # Now make bundle makes main.tar # # Revision 1.4 1994/10/24 17:45:58 gaertner # Doesn't create a debug version anymore. # # Revision 1.3 1994/10/24 17:14:14 gaertner # Installs pretzel to ../../bin when you `make install'. # # Revision 1.2 1994/10/21 17:36:00 gaertner # Compiles with PRETZEL_DEBUG set. # # Revision 1.1 1994/10/21 17:16:54 gaertner # Initial revision # # pretzel-2.0n-2/main/pascal.correct.y0000644000000000000000000002000106631470061016070 0ustar rootroot/************************************************** * This is a prettyprinting parser implementation * * file generated by pretzel. (It's Bison code!) * * * *************************************************/ %{ /* this is needed for the yyprint function below */ #include /* include the attribute definitions */ #include"attr.h" /* include the output definitions */ #include"output.h" /* enable parser debugging */ #define YYDEBUG 1 /* redefine the semantic value */ #define YYSTYPE Attribute* /* enable calls of YYPRINT */ #define YYPRINT(file, type, value) yyprint (file, type, value) /* this is the prototype for yyprint */ static void yyprint(FILE *file, int type, YYSTYPE value); /* make sure that our local copy of yylex is * declared with name `yylex' and as a static * function. This should trick the parser into * calling the scanner object stored in * `static_scanner' (see below). */ /* undefine yylex to make sure it isn't renamed * by any command line option (e.g. -P). */ #undef yylex /* declare our local `dummy' yylex */ static int yylex(YYSTYPE *rvalue); /* make sure any newer versions of Bison don't * redeclare it differently */ #define YYLEX_DECL %} /************************************************* * various user definitions start here: * *************************************************/ /* makeWEAVE definitions for a parser for simple formatted * PASCAL code. (preBISON file of makeWEAVE) */ %token SEMI %token BEG %token END %token MATH %token SIMP %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %{ #define YYDEBUG 1 %} /************************************************* * some pretzel definitions start here: * ************************************************/ %{ /* include own header only in default case: */ #ifndef PPARSE_NAME #include "Ppparse.h" #endif /* this is a definition of the yyerror routine */ yyerror (const char *s) { /* ignore error messages by BISON */ /* trick! use s do get around warning `s not used'. */ if (1==0) fprintf(stderr, "%s", s); return 0; } /* enable parser debugging */ #define YYDEBUG 1 /* variable to hold the parsed attribute */ static Attribute *rest=create(null); /* include the scanner only in the default case: */ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* trick the yyparse function to use the scan member * of the scanner class: */ static Pscan* static_scanner = NULL; static int yylex( YYSTYPE *rvalue ) { return(static_scanner->scan(rvalue)); } %} %pure_parser %% stmt_list : stmt {rest=$$=$1;} | stmt_list SEMI stmt { rest=$$= join( join( join( $1, $2), create(force)), $3); } | SEMI { rest=$$= join( create("Hallo"), create(null)); } | stmt_list SEMI { rest=$$= join( $1, $2); } ; stmt : BEG stmt_list END { rest=$$= join( join( join( join( join( join( join( $1, create(indent)), create("[3]")), create(force)), $2), create(outdent)), create(force)), $3); } | math {rest=$$=$1;} ; math : MATH {rest=$$=$1;} | math math {rest=$$=join($1,$2);} | SIMP {rest=$$=$1;} | OPEN math CLOSE {rest=$$=join($1,join($2,$3));} ; stmt : ALPHA math OMEGA stmt { rest=$$= join( join( join( join( join( join( join( join( join( $1, create(" ")), $2), create(" ")), $3), create(indent)), create("[2]")), create(force)), $4), create(outdent)); } ; stmt : BEG stmt_list UNTIL math { rest=$$= join( join( join( join( join( join( join( join( $1, create(indent)), create("[1]")), create(force)), $2), create(outdent)), create(force)), $3), $4); } ; proc : proc INTRO math SEMI { rest=$$= join( join( join( join( $1, $2), $3), $4), create(force)); } | proc stmt { rest=$$= join( join( $1, $2), create(force)); } | PROC {rest=$$=$1;} ; stmt : INTRO math SEMI { rest=$$= join( join( join( $1, $2), $3), create(force)); } ; %% /************************************************* * additional pretzel code starts here: * *************************************************/ #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif PPARSE_NAME::PPARSE_NAME() { } PPARSE_NAME::~PPARSE_NAME() { static_scanner = NULL; } int PPARSE_NAME::prettyprint(istream* is, ostream* os) { Latex_cweb_output ppoutput(*os); return(prettyprint(is, &ppoutput)); } int PPARSE_NAME::prettyprint(istream* is, Output* outp) { int ret_val = 0; PSCAN_NAME ppscanner(is); static_scanner = &ppscanner; ret_val=yyparse(); while (!(is->eof())) { char c; is->get(c); } rest->print(*outp); return(ret_val); } void PPARSE_NAME::debug_on() { yydebug = 1; } void PPARSE_NAME::debug_off() { yydebug = 0; } /* This is a routine to print the semantic value */ static void yyprint(FILE *file, int type, YYSTYPE value) { Latex_cweb_output os(cerr); value->print(os); } /************************************************* * optional user defined C code follows here: * *************************************************/ pretzel-2.0n-2/main/pascal.fg0000644000000000000000000000172306156053674014577 0ustar rootroot/* makeWEAVE definitions for a parser for simple formatted * PASCAL code. (preBISON file of makeWEAVE) */ %token SEMI %token BEG %token END %token MATH %token SIMP %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %{ #define YYDEBUG 1 %} %% stmt_list : stmt | stmt_list SEMI stmt {$1 + $2 + force + $3} | SEMI {"Hallo" + null} | stmt_list SEMI { $1 + $2} ; stmt : BEG stmt_list END {$1 + indent + "[3]" + force + $2 + outdent + force + $3 } | math ; math : MATH | math math | SIMP | OPEN math CLOSE ; stmt : ALPHA math OMEGA stmt {$1 + " " + $2 + " " + $3 + indent + "[2]" + force + $4 + outdent } ; stmt : BEG stmt_list UNTIL math {$1 + indent +"[1]" + force + $2 + outdent + force + $3 + $4 } ; proc : proc INTRO math SEMI {$1 + $2 + $3 + $4 + force} | proc stmt {$1 + $2 + force} | PROC ; stmt : INTRO math SEMI {$1 + $2 + $3 + force} ; pretzel-2.0n-2/main/pascal.correct.l0000644000000000000000000001576310765025321016074 0ustar rootroot/************************************************ * This is a flex file generated by pretzel * * * ************************************************/ %{ /* some needed headers: */ #include #include"attr.h" /* we'll define yywrap() which is needed for the scanner * here, so we won't have to bother about it if we're * doing the standard case. You can define your own version * by #undef'ing PSCAN_YYWRAP and supplying your own definition * in the definitions section. */ #define PSCAN_YYWRAP /* input will come from this istream */ static istream * yyin_stream; /* redefine YYINPUT to read from input streams */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } %} /* this is an example formatted token file for a pascal * prettyprinter. */ /************************************************ * some pretzel definitions start here: * ***********************************************/ %{ /* the default name of the include file with the token * code definitions is stored in PTOKDEFS_NAME and * defaults to `ptokdefs'. */ #ifndef PTOKDEFS_NAME #define PTOKDEFS_NAME "ptokdefs.h" #endif /* now we have to include the token definitions */ #include PTOKDEFS_NAME /* allow user to choose generated scanner class name*/ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* redefine the interface of the scanner */ #undef YY_DECL #define YY_DECL int yylex (Attribute**rvalue) /* here's the standard version of yywrap() */ #ifdef PSCAN_YYWRAP extern "C" int yywrap() { return(1); } #endif %} %% "<>" { *rvalue=join( create("$\\neq$")); return(MATH);} "<=" | ">=" | ":=" {*rvalue=create(yytext);return (MATH);} '[^'|'']*' {*rvalue=create(yytext);return (SIMP);} "(" {*rvalue=create(yytext);return (OPEN);} ")" {*rvalue=create(yytext);return (CLOSE);} "[" {*rvalue=create(yytext);return (OPEN);} "]" {*rvalue=create(yytext);return (CLOSE);} "*" {*rvalue=create(yytext);return (MATH);} "," { *rvalue=join( join( create(yytext), create(opt9) )); return(MATH);} ".." {*rvalue=create(yytext);return (MATH);} "." {*rvalue=create(yytext);return (SIMP);} ":" {*rvalue=create(yytext);return (COLON);} ";" {*rvalue=create(yytext);return (SEMI);} "=" {*rvalue=create(yytext);return (MATH);} "+" {*rvalue=create(yytext);return (MATH);} [0-9]+ {*rvalue=create(yytext);return (SIMP);} [0-9]*"."[0-9]+ {*rvalue=create(yytext);return (SIMP);} and {*rvalue=create(yytext);return (MATH);} array {*rvalue=create(yytext);return (ALPHA);} begin { *rvalue=join( join( create(force), create(yytext) )); return(BEG);} case { *rvalue=join( join( create(force), create(yytext) )); return(ALPHA);} const { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(INTRO);} div {*rvalue=create(yytext);return (MATH);} do {*rvalue=create(yytext);return (OMEGA);} downto {*rvalue=create(yytext);return (MATH);} else {*rvalue=create(yytext);return (ELSE);} end {*rvalue=create(yytext);return (END);} for {*rvalue=create(yytext);return (ALPHA);} function { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(PROC);} if { *rvalue=join( join( join( create("{\\bf "), create(yytext) ), create("}") )); return(ALPHA);} mod {*rvalue=create(yytext);return (MATH);} not {*rvalue=create(yytext);return (MATH);} of {*rvalue=create(yytext);return (OMEGA);} or {*rvalue=create(yytext);return (MATH);} procedure | program { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(PROC);} record {*rvalue=create(yytext);return (BEG);} repeat { *rvalue=join( join( create(force), create(yytext) )); return(BEG);} then {*rvalue=create(yytext);return (OMEGA);} to {*rvalue=create(yytext);return (MATH);} type { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(INTRO);} until { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(UNTIL);} var { *rvalue=join( join( join( create(force), create(backup) ), create(yytext) )); return(INTRO);} while { *rvalue=join( join( create(force), create(yytext) )); return(ALPHA);} [a-zA-Z][a-zA-Z0-9\_]* {*rvalue=create(yytext);return (SIMP);} [\t\ \n] /* empty */ . /* empty */ %% /************************************************ * additional pretzel C code follows here: * ***********************************************/ PSCAN_NAME::PSCAN_NAME (istream* is ) : Pscan(is) { yyin_stream = is; } int PSCAN_NAME::scan(Attribute* *rvalue) { return(yylex(rvalue)); } PSCAN_NAME::~PSCAN_NAME () { yyrestart(NULL); } /************************************************ * additional user defined C code follows here: * ***********************************************/ /* here's some additional C code */ pretzel-2.0n-2/include/0000755000000000000000000000000010765026553013507 5ustar rootrootpretzel-2.0n-2/pretzel-it/0000755000000000000000000000000006631467443014167 5ustar rootrootpretzel-2.0n-2/pretzel-it/pretzel-it0000755000000000000000000002322106631467443016214 0ustar rootroot#!/bin/sh # $Id: pretzel-it,v 2.2 1998/12/03 10:58:39 felix Exp $ #---------------------------------------------------------------------- # # pretzel-it --- transform input files into a pretzel prettyprinter # # (history at end) # SYNOPSIS # # pretzel-it [-iqvdnh] language ppname # # # pretzel-it tries to produce a prettyprinter from the input files # `language.ft' and `language.fg'. The prettyprinter is encapsulated in # a minimal main program called `ppname'. It's usgage then is: # # ppname tex-code # # pretzel-it will leave the C code of the prettyprinter in the current # directory. If the -i option is given, all intermediate files, such # as the flex and Bison files, as well as the object code of the C # files are left there too. # # Filenames of the C code are: language.lex.c, language.tab.c and # ptokdefs.h for the token header. # # pretzel-it expects to find the `pretzel' program in your PATH. Also # it looks for the pretzel library and include files in the directories # specified by the environment variables PRETZEL_LIBDIR and PRETZEL_INCLUDE. # # # OPTIONS # # -i don't remove intermediate products (flex/Bison source # and prettyprinter object code) # -q run quietly # -v verbose, print commands before invoking (for debugging) # -d turn prettyprinter debugging features on by default, # produce an .output file for detailed diagnosis of parser # (for debugging the prettyprinting grammar) # -h print help message # # -n noweb option: instead of producing a standalone # prettyprinter `ppname' it will produce a noweb # prettyprinting filter `ppname' that can be used as # additional filter with noweb's -filter option # (and LaTeX as typesetter). Without the -i option # it will remove _all_ intermediates and leave only the # filter in the current directory. # # # CAVEATS: # # pretzel-it is very simple and will only produce default # prettyprinters. Use the specialized Makefile if you want to do # special things like using several prettyprinters within one # program. # # The noweb option is new and very experimental. # # # IMPLEMENTATION NOTES # # After checking the arguments, the commands that are used to # invoke flex, Bison and the compiler are pieced together and then # executed. # # The noweb option builds a normal prettyprinter but links it with # a different main function and removes all intermediates. # cmd=`basename $0` usage() { echo "usage: $cmd [-inqvdh] language ppname" >&2 echo "use -h option for full usage" >&2 exit 1 } full_usage() { echo "usage: $cmd [-inqvdh] language ppname" >&2 echo "options: " >&2 echo " -i don't remove intermediate products" >&2 echo " -q run quietly" >&2 echo " -v verbose, print commands before invoking" >&2 echo " -d turn prettyprinter debugging features on" >&2 echo " -h print this help message" >&2 echo " -n (experimental) noweb option" >&2 exit 0 } envnote() { echo "you need to set the environment variables" >&2 echo "PRETZEL_LIBDIR and PRETZEL_INCLUDE to the" >&2 echo "pretzel library and include directories." >&2 exit 1 } # normalize and check arguments: cleanup_intermediates=true run_noisy=true verbose_mode='' build_debug_pp='' noweb_mode='' while getopts 'iqvdnh' option do case "$option" in i) cleanup_intermediates='' ;; q) run_noisy='' ;; v) verbose_mode=true ;; d) build_debug_pp=true ;; n) noweb_mode=true ;; h) full_usage ;; # add more options here *) usage ;; esac done # number of remaining arguments has to be 2: shift `expr $OPTIND - 1` test $# -eq 2 || usage # check if environment variables have been set test $PRETZEL_LIBDIR || export PRETZEL_LIBDIR=/usr/lib/pretzel # envnote test $PRETZEL_INCLUDE || export PRETZEL_INCLUDE=/usr/include/pretzel # envnote # ----------------------------------------------------------------- # Build commands that are invoked by the script: pretzel_command="pretzel -q $1" bison_command="bison -d $1.y -o $1.tab.c" # -v flag produces the .output file for detailed diagnosis debug_bison_command="bison -v -d $1.y -o $1.tab.c" after_bison="mv $1.tab.h ptokdefs.h" flex_command="flex -t $1.l > $1.lex.c" # don't need link commands on command line compile_flex="g++ -c -I$PRETZEL_INCLUDE -g $1.lex.c" compile_bison="g++ -c -I$PRETZEL_INCLUDE -g $1.tab.c" # note that the order of the arguments is important for portability link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/plainpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # this is used if you're building a prettyprinter for debugging debug_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/plaindpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # cleanup_command="rm -f $1.l $1.y $1.lex.o $1.tab.o" # special noweb command (invoked instead of the normal link commands): noweb_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/nowebpretzelpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # currently the same as noweb_link_command: noweb_debug_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/nowebpretzelpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" noweb_cleanup_command="rm -f $1.l $1.y $1.lex.o $1.tab.o $1.lex.c \ $1.tab.c ptokdefs.h" # ------------------------------------------------------------------ # now go to work: let's run the different programs on the files one # at a time and be sure to bail out when one of them returns with an # error. # now go to work: run pretzel on the input files. if [ "$run_noisy" ] then echo "starting to pretzel..." fi if [ "$verbose_mode" ] then echo $pretzel_command fi eval $pretzel_command || exit 1 # now run flex and Bison on them and try to compile... if [ "$run_noisy" ] then echo "preprocessing..." fi if [ "$verbose_mode" ] then echo $bison_command fi if [ "$build_debug_pp" ] then eval $debug_bison_command || exit 1 else eval $bison_command || exit 1 fi eval $after_bison if [ "$verbose_mode" ] then echo $flex_command fi eval $flex_command || exit 1 if [ "$run_noisy" ] then echo "processing .ft file..." fi if [ "$verbose_mode" ] then echo $compile_flex fi eval $compile_flex || exit 1 if [ "$run_noisy" ] then echo "processing .fg file..." fi if [ "$verbose_mode" ] then echo $compile_bison fi eval $compile_bison || exit 1 if [ "$build_debug_pp" ] then if [ "$noweb_mode" ] then # case 1: debug and noweb if [ "$run_noisy" ] then echo "building noweb filter $2 (turning debug features on)..." fi if [ "$verbose_mode" ] then echo $noweb_debug_link_command fi eval $noweb_debug_link_command || exit 1 else # case 2: debug and not noweb if [ "$run_noisy" ] then echo "building prettyprinter $2 (turning debug features on)..." fi if [ "$verbose_mode" ] then echo $debug_link_command fi eval $debug_link_command || exit 1 fi else if [ "$noweb_mode" ] then # case 3: normal noweb if [ "$run_noisy" ] then echo "building noweb filter $2..." fi if [ "$verbose_mode" ] then echo $noweb_link_command fi eval $noweb_link_command || exit 1 else # case 4: normal if [ "$run_noisy" ] then echo "building prettyprinter $2..." fi if [ "$verbose_mode" ] then echo $link_command fi eval $link_command || exit 1 fi fi # if [ "$cleanup_intermediates" ] then if [ "$noweb_mode" ] then if [ "$run_noisy" ] then echo "cleaning up and leaving only noweb filter..." fi if [ "$verbose_mode" ] then echo $noweb_cleanup_command fi eval $noweb_cleanup_command else # cleanup but not in noweb mode if [ "$run_noisy" ] then echo "cleaning up..." fi if [ "$verbose_mode" ] then echo $cleanup_command fi eval $cleanup_command fi fi if [ "$run_noisy" ] then echo "done." fi #====================================================================== # # $Log: pretzel-it,v $ # Revision 2.2 1998/12/03 10:58:39 felix # can use standard search paths for PRETZEL_XXX if variables are # not set (thanks to I think Dave Wilson). # # Revision 2.1 1998/04/25 08:03:09 gaertner # produces .output file from bison when -d option is given for # detailed grammar diagnosis in the presence of conflicts. # # Revision 2.0 1996/12/16 17:35:52 gaertner # release 2.0 # # Revision 1.10 1996/11/14 18:13:23 gaertner # noweb option should work now. Changes the text lines that are # printed out to the screen because they show too many internals. # # Revision 1.9 1996/11/14 18:03:13 gaertner # Added noweb option. Added -h option. # # Revision 1.8 1996/09/17 13:46:37 gaertner # Changed CC to g++ in compiler lines. Also added the `cleanup' option. # # Revision 1.7 1996/03/22 10:10:11 gaertner # added -d option for grammar debugging. # # Revision 1.6 1996/03/21 11:08:29 gaertner # Corrected argument checking and enhanced documentation. # # Revision 1.5 1996/02/06 19:24:59 gaertner # Added new options -i -q -v. Bails out when an error is encountered. # Invoked commands are configured in one place to ease maintenance. # # Revision 1.4 1996/02/06 17:28:07 gaertner # Version before re-writing the tool. # # Revision 1.3 1995/08/30 17:51:57 gaertner # tex->lex in rm-line. # # Revision 1.2 1995/08/30 17:48:41 gaertner # Moved link objects to the front of the compiler line. Some # compilers need this. # # Revision 1.1 1995/08/30 17:45:49 gaertner # Initial revision # # pretzel-2.0n-2/pretzel-it/index.list0000644000000000000000000000020306360716406016161 0ustar rootrootthis directory & the pretzel-it shell script Makefile & the Makefile pretzel-it & the script itself test.fg & test input test.ft & pretzel-2.0n-2/pretzel-it/test.fg0000644000000000000000000000017406124232401015443 0ustar rootroot/* pretzel formatted grammar for testing */ %token ID_TYPE %% stmt : ID_TYPE { $1 + force + "\n" } ; pretzel-2.0n-2/pretzel-it/index.html0000644000000000000000000000160106360716416016156 0ustar rootroot Index file for directory "pretzel/pretzel-it" of Pretzel distribution

Index file for directory "pretzel/pretzel-it" of Pretzel distribution

Files and directories are:

this directory

    the pretzel-it shell script
Makefile
    the Makefile
pretzel-it
    the script itself
test.fg
    test input
test.ft

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 16:15:43 MESZ 1997 pretzel-2.0n-2/pretzel-it/Makefile0000644000000000000000000001021706631467310015621 0ustar rootroot# $Id: Makefile,v 2.1 1998/12/03 10:57:53 felix Exp $ # ---------------------------------------------------------------------- # # Makefile for pretzel-it # # It's not much of a Makefile. It's mainly for making a release # and testing. # # (Note that the .tex.dvi implicit rule uses LaTeX instead of TeX) # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = CC # de-comment this if you want a debug version: #DBVERSION = -D PRETZEL_DEBUG # compiler flags: CFLAGS = -g -I../include -L.. -lpretzel # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # You probably don't need to change anything from here: # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # Groups of files: # all `WEB' sources WEBS = # all other program WEB sources ETCWEBS = # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = # name of the distribution package DISTNAME = # Which program to make by default: PROG = pretzel-it # objects of this program: OBJS = dummy # C sources of this program: CSRCES = # all stuff to be removed too: OTHERCRAP = ptokdefs.h test.l test.y test.lex.c test.lex.o test.tab.c \ test.tab.o test.y testpp # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) # these are all header files produced from WEBs that may appear ALLHEADERS = # these are all the executables that could be produced ALLPROGS = $(PROG) # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex -d #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = latex # ---------------------------------------------------------------------- .SUFFIXES: .spc .ps .tex .dvi .w .c .o .h # overall rules: .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) $(CCFLAGS) -c $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) echo You can only make regression here # $(CC) $(OBJECTS) $(CCFLAGS) -o $@ $(OBJS): $(HEADERS) $(CSRCES) # list all source code: print: # apply lint to all C sources: lint: # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(OTHERCRAP) # remove everything that doesn't belong to original source: clobber: clean # bundle source files together into an archive: bundle: tar cf $(DISTNAME).tar \ $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # make a regression test: regression: ./pretzel-it -h ./pretzel-it -v test testpp # if { diff pascal.l pascal.correct.l && \ # diff pascal.y pascal.correct.y; } \ # then echo "Regression test is fine."; \ # else echo "Regression test failed."; \ # fi # copy executables into PATH directories, et al. release: cp $(PROG) ../bin # ====================================================================== # # $Log: Makefile,v $ # Revision 2.1 1998/12/03 10:57:53 felix # added ./ to invocations of pretzel-it # # Revision 2.0 1996/12/16 17:38:32 gaertner # release 2.0 # # Revision 1.2 1996/02/06 19:24:31 gaertner # Added a few small things to be able to simply make a regression test. # # Revision 1.1 1996/02/06 18:22:36 gaertner # Initial revision # pretzel-2.0n-2/pretzel-it/test.ft0000644000000000000000000000034006105716322015463 0ustar rootroot/* this is a test formatted token file for a dumb prettyprinter. */ %% [a-zA-Z][a-zA-Z0-9]* ID_TYPE // identifiers [\t\ \n] // eat up whitespace . // eat up other non matching characters pretzel-2.0n-2/index.list0000644000000000000000000000144106360133221014053 0ustar rootroot this directory & Main directory of the Pretzel distribution COPYING & Copying Conditions (GNU GPL) Makefile & Top Level Makefile README & README file of Pretzel TODO & List of things to do alloca.c & Fix to the GNU malloc function attr & The Attribute class bin & binaries contrib & Contributed software (noweb stuff is here) diary & Diary of Pretzel diary-1.1 & Diary of Pretzel up to version 1.1 doc & Documentation (PretzelBook is here) fgrammar & Prettyprinter generator function ftokens & Prettyprinting scanner include & include files for runtime library index.html & this file index.list & list of files for index.html languages & example plain Pretzel grammars main & The main Pretzel program man & Manual pages output & The Output class pretzel-it & The pretzel-it shell script pretzel-2.0n-2/output/0000755000000000000000000000000010765026553013424 5ustar rootrootpretzel-2.0n-2/output/outtest.nw0000644000000000000000000000476210765025560015507 0ustar rootroot% This is a file written using noweb % % $Id: outtest.nw,v 1.1 1996/03/13 11:29:02 gaertner Exp $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{Testing the [[Output]] Class} \author{Felix G\"artner} \maketitle %\begin{abstract} % XXX %\end{abstract} \tableofcontents \section{Introduction} This is a short program to have a little confidence that the output class is doing what it should do. We'll test the output class a few times: First in normal mode and then in debug mode. <>= #include using namespace std; #include"output.h" <> <> int main() { cout << "Starting to test the outputs..." << endl; <> <> <> cout << "Done." << endl; return 0; } @ Testing is done on an output object that will be global and simply called |o|. It is connected with the standard output. <>= Latex_cweb_output o(cout); @ To have the code written only once, here's a function that does the testing. It creates various calls of |do_output| and thus invokes action within the output routine. <>= void do_testing() { o.do_output("if"); o.do_output(" "); o.do_output("(x<0)"); o.do_output(" "); o.do_output("then"); o.do_output(indent); o.do_output(force); o.do_output("begin"); o.do_output(" "); o.do_output("abs"); o.do_output(":="); o.do_output("-1"); o.do_output(" "); o.do_output("end"); o.do_output(";"); o.do_output(outdent); o.do_output(force); o.do_output(""); /* to flush output */ return; } @ The first test is done in normal mode. We'll switch the debug mode on and off again once to look what happens. <>= cout << "Doing first round of testing:" << endl; o.debug_on(); o.debug_off(); do_testing(); cout << endl << endl; @ The second round is done in debug mode. <>= cout << "Doing second round of testing:" << endl; o.debug_on(); do_testing(); o.debug_off(); cout << endl << endl; @ The third go uses \C\ comments as debug delimiters. <>= cout << "Doing third round of testing:" << endl; o.debug_on("/*","*/"); do_testing(); o.debug_off(); cout << endl << endl; @ \end{document} % % $Log: outtest.nw,v $ % Revision 1.1 1996/03/13 11:29:02 gaertner % Initial revision % % pretzel-2.0n-2/output/blankoutput.nw0000644000000000000000000002334606467622475016363 0ustar rootroot% This is a file written using noweb % % $Id: blankoutput.nw,v 1.1 1996/03/13 11:29:37 gaertner Exp $ % % INSTRUCTIONS: Rename this file to the name of your subclass. Search % for places marked XXXX and replace the `XXXX' with an unique % identifier for your subclass. Then search for XXX and adjust the % code and documentation. % % \documentclass{article} \usepackage{a4,pretzeldoc,version,noweb} \begin{document} \includeversion{bigspecs} \includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification %\excludeversion{impls}% without implementation \title{XXX% % put the name of your subclass here \thanks{This file is based on a template for a subclass of the [[Output]] class written by Felix G\"artner.}} \author{XXX} % put your own name here \maketitle \begin{abstract} % fill in the abstract at the places marked XXX or write your own This file contains a subclass of the [[Output]] class called XXX. It can be used to create a prettyprinter for a XXX output device. It belongs to a framework supplied by the ``pretzel'' prettyprinter generator. \end{abstract} \tableofcontents % Fill in the places marked XXX or write your own text. \section{Introduction} This text describes the specification \begin{impls}and implementation\end{impls} for a new subclass of the \CPP\ [[Output]] class. It specializes on the XXX output device. It is a contribution to the ``pretzel'' system, a prettyprinter generator written by Felix G\"artner (\verb+theedge@rbg.informatik.th-darmstadt.de+). For more examples of this kind of thing consult the files {\tt output.nw}, {\tt asciioutput.nw} and {\tt blankoutput.nw} included in the pretzel distribution. @ Here's the frame of the header for the new subclass. <

>= #ifndef XXX_H #define XXX_H #include "output.h" /* base class defined in here */ <
> <> <> #endif @ At the moment, we don't need more headers. <
>= @ \begin{impls} Here's the framework of the implementation. <>= #include "XXX.h" <
> <> @ \end{impls} In the following section of this document we will explain the purpose of this subclass and the results obtained when using it together with pretzel. This is the interface of the class. It will be described mainly \C\ preprocessor macros. First of all, this is what the name of the subclass will look like in the program: % Fill in the name of your class here. The first XXXX has to be % replaced by the new name too, since we might want to use several % subclasses in a single program and the macro definitions would % define the same macro. <>= #define XXXX_SUBCLASS_NAME XXXX @ \section{Interface} The actual declaration of the new subclass is pretty simple, once we've defined the name. <>= class XXXX_SUBCLASS_NAME : public Output { public: XXXX_SUBCLASS_NAME(ostream& ostr) : Output(ostr) {}; ~XXXX_SUBCLASS_NAME() { flush_output(); }; private: void flush_output(); }; @ Yes, it`s as simple as that. The only thing needed to write now is the [[flush_output]] routine, which is a pure virtual function inside the [[Output]] base class. The main parts of this routine are always identical. The only differences are the different things done when format commands are interpreted. % XXX % There are two possibilities now: If your target is a markup % typesetting system, you can simply replace the strings here and % that's that. % However, if the interpretation of the format commands needs some % explicit programming, you have to go into the implementation below % and code the things yourself. These things can be defined here using macro definitions again. Here we specify the strings output to the internal output steam when the corresponding format commands are interpreted. Other concrete actions are coded directly in the implementation of [[flush_output]] below. % XXX fill in the strings here and explain what they do. <>= #define XXXX_NULL_OUTPUT_STRING "" #define XXXX_INDENT_OUTPUT_STRING "" #define XXXX_OUTDENT_OUTPUT_STRING "" #define XXXX_OPT0_OUTPUT_STRING "" #define XXXX_OPT1_OUTPUT_STRING "" #define XXXX_OPT2_OUTPUT_STRING "" #define XXXX_OPT3_OUTPUT_STRING "" #define XXXX_OPT4_OUTPUT_STRING "" #define XXXX_OPT5_OUTPUT_STRING "" #define XXXX_OPT6_OUTPUT_STRING "" #define XXXX_OPT7_OUTPUT_STRING "" #define XXXX_OPT8_OUTPUT_STRING "" #define XXXX_OPT9_OUTPUT_STRING "" #define XXXX_BACKUP_OUTPUT_STRING "" #define XXXX_BREAKSPACE_OUTPUT_STRING "" #define XXXX_FORCE_OUTPUT_STRING "" #define XXXX_BIGFORCE_OUTPUT_STRING "" #define XXXX_NOINDENT_OUTPUT_STRING "" #define XXXX_CANCEL_OUTPUT_STRING "" @ To use this new output, you`ll have to build a prettyprinter with pretzel and specify XXX as output class to use. % put more text describing the use of the class here XXX @ \section{Implementation of [[flush_output]]} As part of the implementation, here's an explanation how the typesetter dependent parts of the new subclass work. Essentially this is an explanation of an example implementation of the virtual [[flush_output]] routine. @ Here`s the frame of [[flush_output]]. It will always be called when the lookahead needs to be cleared. If the lookahead is empty, we don`t need to do anything. <>= void XXXX_SUBCLASS_NAME::flush_output() { if (next_output_type==empty) return; /* otherwise: */ <> next_output_type=empty; } @ Ok, so now let's turn to the part, where format commands are actually interpreted. Suppose the next format command to be interpreted is stored in [[next_output]]; the only thing to do now is to have a giant switch inspecting [[next_output]]. Every case in this switch outputs the corresponding code for this case to the [[ostream os]] that is connected to our output class object. <>= <> switch (next_output) { <> default: <> break; }; @ <>= if (debug_mode==yes) { os << begin_string << Format_command_str[next_output] << end_string; } @ This shouldn't (can't) happen. <>= cerr << endl << "Unknown format command detected! Something's wrong here." << endl << endl; exit(EXIT_FAILURE); @ To use [[exit]], we have to include this: <
>= #include @ And since some (really old) operating systems don't have the common [[EXIT_FAILURE]] and [[EXIT_SUCCESS]] macros defined (in [[stdlib.h]]), we'll define them here. <
>= #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif @ \section{Interpretation of Format Commands} Now we will start to scan the cases in the big switch. The actions performed are essentially the output of a special string defined in the interface above. However, special actions are directly coded here. % XXX code the special actions and write what you're doing \subsection{The [[null]] format command} <>= case null: os << XXXX_NULL_OUTPUT_STRING ; break; @ \subsection{The [[indent]] and [[outdent]] format commands} <>= case indent: os << XXXX_INDENT_OUTPUT_STRING ; break; case outdent: os << XXXX_OUTDENT_OUTPUT_STRING ; break; @ \subsection{The [[opt]] format command} The next cases handle the 10 instances of the [[opt]] command. <>= case opt0: os << XXXX_OPT0_OUTPUT_STRING ; break; case opt1: os << XXXX_OPT1_OUTPUT_STRING ; break; case opt2: os << XXXX_OPT2_OUTPUT_STRING ; break; case opt3: os << XXXX_OPT3_OUTPUT_STRING ; break; case opt4: os << XXXX_OPT4_OUTPUT_STRING ; break; case opt5: os << XXXX_OPT5_OUTPUT_STRING ; break; case opt6: os << XXXX_OPT6_OUTPUT_STRING ; break; case opt7: os << XXXX_OPT7_OUTPUT_STRING ; break; case opt8: os << XXXX_OPT8_OUTPUT_STRING ; break; case opt9: os << XXXX_OPT9_OUTPUT_STRING ; break; @ \subsection{The [[backup]] format command} <>= case backup: os << XXXX_BACKUP_OUTPUT_STRING ; break; @ \subsection{The [[break_space]] format command} <>= case break_space: os << XXXX_BREAKSPACE_OUTPUT_STRING ; break; @ \subsection{The [[force]] format command} <>= case force: os << XXXX_FORCE_OUTPUT_STRING ; break; @ \subsection{The [[big_force]] format command} <>= case big_force: os << XXXX_BIGFORCE_OUTPUT_STRING ; break; @ \subsection{The [[no_indent]] format command} <>= case no_indent: os << XXXX_NOINDENT_OUTPUT_STRING ; break; @ \subsection{The [[cancel]] format command} <>= case cancel: os << XXXX_CANCEL_OUTPUT_STRING ; break; @ \end{document} % % $Log: blankoutput.nw,v $ % Revision 1.1 1996/03/13 11:29:37 gaertner % Initial revision % % pretzel-2.0n-2/output/asciioutput.dvi0000644000000000000000000003611406255301575016505 0ustar rootroot÷ƒ’À;è TeX output 1996.12.16:1814‹ÿÿÿÿ É ýC Ÿ ý®‘Èó߆µTG® cmtt12»Ascii_terminal_outputŸùº¯ó!",š cmsy10ÀŽŽŽŸ‘9h×óDÓítG®G®cmr17ºAn–7t»Output“ºSubsŽclass“for“Screen“or“Line“PrinŒqterŽŸ’¹Þ„óX«Q cmr12¼F‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸˆ‹’«ßúDecem¬rbSŽer–ê¨16,“1996ŽŸ,™»’È Ãót ‰: cmbx9ÉAbstractŽŸù®‘NŸ¨óo´‹Ç cmr9ÈThis–8 le“con¾9tains“a“subAÇclass“of“the“óߤN cmtt9ÊOutput“Èclass“called“ÊAscii_terminal_outputÈ.ޤ ‘@¿®It–a²can“bšAÇe“used“to“create“a“prett•¾9yprin“ter–a²for“a“normal“terminal“screen.‘ŠIt“b˜e-Ž¡‘@¿®longs–Tto“a“framewš¾9ork“supplied“b˜y“the“\pretzel"“prett˜yprin˜ter“generator.ŽŸ òê‘'¿¬ó!ÂÖN ff cmbx12ÌCon•ŒÌten“tsޤ‘'¿¬ó"ò"V cmbx10Í1Ž‘6¿­In®9troQÇduction’2“1ŽŽ¡‘'¿¬2Ž‘6¿­In®9terface–ÕTand“Use’û„ 2ŽŽ© ‘6¿­óKñ`y cmr10²2.1Ž‘M¿±AspšGects–UUof“ASCI˜I“T‘ÿ*ªerminal“Output‘Û ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é3ŽŽ¡‘'¿¬Í3Ž‘6¿­Implemen®9tation’š3ŽŽ¦‘6¿­²3.1Ž‘M¿±Implemen¸ãting–UUóßêŸ'EŽ‘ãxX.‘/ But“sometimes“prett˜yprin˜ted“outputŽ¡‘'¿¬to–@Éa“screen“or“an“ASCIGI‘@Äline“prinš¸ãter“is“required.‘jîThis“class“implemen˜ts“this“kind“ofŽ¡‘'¿¬stu .Ž¡‘6¿¬T‘ÿ*ªo–×&actually“build“a“prett•¸ãyprin“ter–×&of“this“kind“yš¸ãou'll“ha˜v˜e“to“extract“a“header“andŽ¡‘'¿¬implemenš¸ãtation–h¨ le“from“this“text,‘m}include“it“in“the“prett˜yprin˜ter“spGeci cation“andŽ¡‘'¿¬spšGecify–UUthis“sub˜class“as“argumenš¸ãt“to“the“actual“prett˜yprin˜ter“ob‘Ž8ject.Ž¡‘6¿¬[Example‘UUmissing]Ž¡‘'¿¬The–BÄactual“declaration“of“the“new“subGclass“is“prettš¸ãy“simple,‘F{once“w˜e'v˜e“de ned“theŽ¡‘'¿¬name.ަ‘ $Á2cŽ‘'¿¬¸hÏDe–ÿ}'clar“ation–“çof“the“new“sub‘ÿ}'class“Á2c¸iŽ’ÃZxŽ¡‘1¿¬¹class–?ýAscii_terminal_output_SUBCLASS_NAME“:“public“Output“{Ž¡‘1¿¬public:Ž¡‘F¿ Ascii_terminal_output_SUBCLASS_NAME(ostream&–?ýostr)“:“Output(ostr)“{};Ž¡‘F¿ ~Ascii_terminal_output_SUBCLASS_NAME()–?ý{“flush_output();“};Ž¡‘1¿¬private:Ž¡‘F¿ void‘?ýflush_output();Ž¡‘1¿¬};Ž¡ŽŸ’Ùìx²2ŽŽŒ‹È É ýC Ÿ ý„‘'¿¬²Y‘ÿ*ªes,‘Pðit`s–žas“simple“as“that.‘Í¢The“only“thing“needed“to“do“no¸ãw“is“think“abGout“theޤ ‘'¿¬actions–Ä@that“ha•¸ãv“e–Ä@to“bGe“done“when“inš¸ãterpreting“format“commands“and“implemen˜tŽ¡‘'¿¬them–Wlwithin“the“¹flush_output“²routine,‘Wòwhic¸ãh“is“a“pure“virtual“function“inside“theŽ¡‘'¿¬¹Output–Ò§²base“class.›é¼The“main“parts“of“this“routine“are“alw•¸ãa“ys‘Ò§iden“tical.˜The‘Ò§onlyŽ¡‘'¿¬di erences–UUare“the“di erenš¸ãt“things“done“when“format“commands“are“in˜terpreted.ŽŸþ6‘'¿¬ó&ÂÖN  cmbx12Ñ2.1Ž‘F¬Aspš`ects–€of“ASCI˜I“T‘þàerminal“OutputŽŸuT‘'¿¬²W‘ÿ*ªe'll–okš¸ãeep“the“ideas“implemen˜ted“here“simple.‘¾ÙThe“format“commands“that“will“bGeŽ¡‘'¿¬implemen¸ãted–UUwill“bGeޤ‘6¿­¸ŽŽŽ‘@¿®¹indent²,‘UU¹outdentŽ¡‘6¿­¸ŽŽŽ‘@¿®¹force²,‘UU¹big_forceŽ¡‘'¿¬²This–¶means“that“no“line“breaking“mecš¸ãhanism“is“implemen˜ted“at“the“momen˜t“(al-ޤ ‘'¿¬though–¥=this“w¸ãould“bšGe“p˜ossible)“and“the“sp˜ecial“commands“¹backup“²and“¹no_indentŽ¡‘'¿¬²will–UUnot“come“out“correctly‘ÿ*ª.Ž¡‘'¿¬The–UUamounš¸ãt“of“inden˜tation“is“de ned“here“(t˜w˜o“blanks“at“presen˜t).Ž©‘ ‘@Á3aŽ‘'¿¬¸hÏMacr‘ÿ}'o–“çde nitions“in“the“implementation“Á3a¸iŽ’ëÔ¼Ž¡‘1¿¬¹#define–?ýAscii_terminal_output_INDENTATION_STRING“"‘ ú"ŽŸ&Ä‘'¿¬Ì3Ž‘@ wImplemenŒÌtationŽŸç‘'¿¬²As–ë´part“of“the“implemenš¸ãtation,‘Ôhere's“an“explanation“ho˜w“the“t˜ypšGesetter“dep˜enden¸ãtŽ¡‘'¿¬parts–bof“the“new“subGclass“w•¸ãork.‘‡îEssen“tially–bthis“is“an“explanation“of“an“exampleŽ¡‘'¿¬implemen¸ãtation–UUof“the“virtual“¹flush_output“²routine.Ž¡‘'¿¬A‘Î lot–Îof“things“can“bGe“de ned“here“using“the“macro“de nitions“here.‘ÝJHere“w¸ãeŽ¡‘'¿¬spšGecify–Ž˜the“strings“output“to“the“in¸ãternal“output“steam“when“the“corresp˜ondingŽ¡‘'¿¬format–UUcommands“are“in¸ãterpreted.ަ‘ \Á3bŽ‘'¿¬¸hÏMacr›ÿ}'o–“çde nitions“in“the“sp˜e˜ci c˜ation“Á2b¸iŽ’Ý9¹²+Ž’å׸ŽŽ¡‘1¿¬¹#define‘?ýAscii_terminal_output_NULL_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_INDENT_OUTPUT_STRING‘$¿ë""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OUTDENT_OUTPUT_STRING‘î""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT0_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT1_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT2_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT3_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT4_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT5_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT6_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT7_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT8_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_OPT9_OUTPUT_STRING‘/?å""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_BACKUP_OUTPUT_STRING‘$¿ë""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_BREAKSPACE_OUTPUT_STRING‘¿÷""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_FORCE_OUTPUT_STRING‘)ÿè"\n"Ž¡‘1¿¬#define‘?ýAscii_terminal_output_BIGFORCE_OUTPUT_STRING‘?ñ"\n\n"Ž¡‘1¿¬#define‘?ýAscii_terminal_output_NOINDENT_OUTPUT_STRING‘?ñ""Ž¡‘1¿¬#define‘?ýAscii_terminal_output_CANCEL_OUTPUT_STRING‘$¿ë""ŽŽŸ’Ùìx²3ŽŽŒ‹· É ýC Ÿ ý„‘6¿¬²Here`s–8Ùthe“frame“of“¹flush_output².‘hHIt“will“alw•¸ãa“ys–8ÙbšGe“called“when“the“lo˜ok‘ÿqÇaheadޤ ‘'¿¬needs–UUto“bšGe“cleared.‘qÇIf“the“lo˜ok‘ÿqÇahead“is“emptš¸ãy‘ÿ*ª,“w˜e“don`t“need“to“do“an˜ything.Ž©y(‘ ‘@Á4aŽ‘'¿¬¸hÏImplementation–“çof“the“new“sub‘ÿ}'class“Á4a¸iŽ’Ö<—Ž¡‘1¿¬¹void‘?ýAscii_terminal_output_SUBCLASS_NAME::flush_output()Ž¡‘1¿¬{Ž¡‘[¿”if‘?ý(next_output_type==empty)Ž¡’…¿|return;Ž¡‘[¿”/*–?ýotherwise:“*/Ž¡‘[¿”¸hÏInterpr›ÿ}'et–“çthe“format“c˜ommand“in“¹next_output“Ïand“write“the“interpr˜etation“to“¹os“Á4b¸iŽŽ¡‘[¿”¹next_output_type=empty;Ž¡‘1¿¬}Ž¡¦‘'¿¬²Ok,›•so–òäno¸ãw“let's“turn“to“the“part,˜where“format“commands“are“actually“in¸ãterpreted.Ž¡‘'¿¬SuppšGose–;the“next“format“command“to“b˜e“in¸ãterpreted“is“stored“in“¹next_output²;‘0™theŽ¡‘'¿¬only–"üthing“to“do“noš¸ãw“is“to“ha˜v˜e“a“gian˜t“switc˜h“inspGecting“¹next_output².‘`ÿEv˜ery“caseŽ¡‘'¿¬in–UUthis“switc¸ãh“outputs“the“correspšGonding“co˜de“for“this“case“to“the“¹ostreamŽ¡‘'¿¬os–UU²that“is“connected“to“our“output“class“ob‘Ž8ject.ަ‘ \Á4bŽ‘'¿¬¸hÏInterpr›ÿ}'et–“çthe“format“c˜ommand“in“¹next_output“Ïand“write“the“interpr˜etation“to“¹os“Á4b¸iŽ’¡¸Ž¡‘1¿¬hÏPrint–“çthe“name“of“the“format“c‘ÿ}'ommand“if“debugging“Á4c¸iŽŽ¡‘1¿¬¹switch‘?ý(next_output)Ž¡‘1¿¬{Ž¡‘F¿ ¸hÏCases–“çof“the“interpr‘ÿ}'etation“switch“in“¹do_output“Á5a¸iŽŽ¡‘F¿ ¹default:‘?ý¸hÏA¾“n–“çunknown“format“c‘ÿ}'ommand!“Á4d¸iŽ’¦kà¹break;Ž¡‘1¿¬};Ž¡ŸòP‘ $Á4cŽ‘'¿¬¸hÏPrint–“çthe“name“of“the“format“c‘ÿ}'ommand“if“debugging“Á4c¸iŽ’9›Ž¡‘1¿¬¹if–?ý(debug_mode==yes)“{Ž¡‘F¿ os‘ ú<<–?ýbegin_string“<<“Format_command_str[next_output]Ž¡‘[¿”<<‘?ýend_string;Ž¡‘1¿¬}ަ‘6¿¬²This–UUshouldn't“(can't)“happGen.ަ‘ \Á4dŽ‘'¿¬¸hÏA¾“n–“çunknown“format“c‘ÿ}'ommand!“Á4d¸iŽ’Ã«’Ž¡‘1¿¬¹cerr–?ý<<“endlŽ¡‘F¿ <<–?ý"Unknown“format“command“detected!“Something's“wrong“here."“<<“endlŽ¡‘F¿ <<‘?ýendl;Ž¡‘1¿¬exit(EXIT_FAILURE);Ž¡¦‘'¿¬²T‘ÿ*ªo–UUuse“¹exit²,“wš¸ãe“ha˜v˜e“to“include“this:ަ‘ $Á4eŽ‘'¿¬¸hÏHe‘ÿ}'ader–“ç les“to“include“in“the“implementation“Á4e¸iŽ’‘׎¡‘1¿¬¹#includeަ‘6¿¬²No•¸ãw›Ú•w“e˜will˜start˜to˜scan˜the˜cases˜in˜the˜big˜switc“h.‘HÝThe˜actions˜pGerformed˜areŽ¡‘'¿¬essenš¸ãtially–Óthe“output“of“a“spGecial“string“de ned“in“the“in˜terface“abGo˜v˜e.‘ë Ho˜w˜ev˜er,Ž¡‘'¿¬as–&:an“ASCIšGI‘&terminal“is“quite“dum•¸ãb,‘Ztw“e–&:need“to“explicitly“co˜de“some“parts“(lik¸ãeŽ¡‘'¿¬managing‘UUinden¸ãtation).ŽŸUð‘'¿¬Ñ3.1Ž‘F¬Implemen ting–€ó'߆µT cmtt12Òindent“Ñand“ÒoutdentŽŸuT‘'¿¬²W‘ÿ*ªe–Öneed“an“inš¸ãternal“coun˜ter“to“hold“the“curren˜t“amoun˜t“of“inden˜tation.‘ôHere's“aŽ¡‘'¿¬static–UUv‘ÿqÇariable“for“this“purpGose.ަ‘ 8^Á4fŽ‘'¿¬¸hÏStatic–“çvariables“in“the“implementation“Á4f‘¡Ç¸iŽ’á«Ž¡‘1¿¬¹static–?ýint“ind“=“0;ŽŽŸ’Ùìx²4ŽŽŒ‹$i É ýC Ÿ ý„‘ ‘@Á5aŽ‘'¿¬¸hÏCases–“çof“the“interpr‘ÿ}'etation“switch“in“¹do_output“Á5a¸iŽ’ å²ޤ ‘1¿¬¹case–?ýindent:“os“<<“Ascii_terminal_output_INDENT_OUTPUT_STRING“;Ž¡‘F¿ ind++;‘?ýbreak;Ž¡‘1¿¬case–?ýoutdent:“os“<<“Ascii_terminal_output_OUTDENT_OUTPUT_STRING“;Ž¡‘F¿ ind--;‘?ýbreak;Ž©Ô“‘6¿¬²The–Sê¹force“²and“¹big_force“²commands“break“the“line“and“add“as“m•¸ãuc“h‘SêwhitespaceŽ¡‘'¿¬as–UUrequired“b¸ãy“¹ind².ަ‘ \Á5bŽ‘'¿¬¸hÏCases–“çof“the“interpr‘ÿ}'etation“switch“in“¹do_output“Á5a¸iŽ’ å²²+Ž’¬Ð¸ŽŽ¡‘1¿¬¹case–?ýforce:“os“<<“Ascii_terminal_output_FORCE_OUTPUT_STRING“;Ž¡‘>= #ifndef OUTPUT_H #define OUTPUT_H <
> <> <> <> #endif @ \begin{impls} The implementation will be described simultaeneously with the specifications. The implementation of the output class is quite simple and rather straightforward. There are, however, a few interesting (and tricky) bits that need special attention. I'll warn you if we come across one of them. The implementation starts off with this chunk. <>= /* this is the implementation of the Output class */ #include"output.h" /* include the own header */ <> <> <> <> @ \end{impls} \section{Format commands} Format commands are abstract instructions for a typesetter or any other output device.\footnote{You can use a markup formatter like \TeX\ or a simple line printer, which of course cannot take on things like automatic line and page breaks, etc. In the following text I will therefore always refer to the output device as the typesetter.} For example they tell the typesetter to force a line break, to add some space to the current amount of indentation or to back up a little. They are abstract in such a way that they can be interpreted differently depending on the capabilities of the typesetter and the taste of the user who is using it. Format commands are intermixed with the prettyprinted source code text in a way specified by the user (using an attribute grammar). See table \ref{tab:formatcommands} for a complete list of all supported format commands. As is shown in the main part of the project documentation, they are sufficient to format all desired features of today's programming languages. The special way in which to use them is again described in the main documentation of this project. % \begin{bigspecs} However I will give a very short example here. \end{bigspecs} \begin{table} \begin{center} \leavevmode \begin{tabular}{lp{8cm}} {\it null} & empty command \\ {\it indent} & indents the next line a little more \\ {\it outdent} & takes back the last indentation (de-indent) \\ {\it force} & forces a line break \\ {\it break\_space} & denotes a possible space for a line break \\ {\it opt$\,n$}, $n \in \{0,\dots,9\}$ & denotes an optional line break with the continuation line indented a litte with respect to the normal starting position. This line break will score a penalty of $10n$.\\ {\it backup} & denotes a small backspace\\ {\it big\_force} & forces a line break and inserts a little extra space \\ {\it no\_indent} & causes the current line to be output flushleft\\ {\it cancel} & obliterates any {\it break\_space}, {\it opt}, {\it force} or {\it big\_force} command that immediatly precedes or follows it and also cancels any {\it backup} command that follows it. \end{tabular} \caption{List of format commands supported by the [[Output]] class.} \label{tab:formatcommands} \end{center} \end{table} \begin{bigspecs} To give you a faint idea of how these format commands work here's a small example that introduce the [[indent]], [[outdent]] and [[force]] commands: \smallskip Say we want to format an \res{if}-\res{then} construct in \PASCAL\ and we want to indent the conditional part of it a little. To achieve this you would have to insert the format commands into the source text as follows: \begin{inp} if a>0 then \fmt{indent} \fmt{force} begin abs := 1 end; \fmt{outdent} \end{inp} \noindent The previous text would yield something like this: \begin{outp} \res{if} $a>0$ \res{then} \myindent\myforce \res{begin} \id{abs}\ass$1$ \res{end};\myoutdent\myforce \end{outp} \noindent This example shows nicely that \fmt{indent} and \fmt{outdent} only take effect after a line break, e.g.~they determine the indentation of the following line. This is useful if you sometimes want a line break and other times you don't. For example you could only want a line break in the previous example if there are \res{begin} and \res{end} keywords in the source code. If they are missing you might want to have the formatting like this: \begin{outp} \res{if} $a>0$ \res{then} \id{abs}\ass$1$; \myforce \end{outp} \noindent The only thing you have to do is {\em not} to insert a \fmt{force}. This leaves you free to insert \fmt{indent}s and \fmt{outdent}s automatically before and behind the conditional part of the construct, as is usefull during automatic parsing of this small example. Again you must confer the main documentation of this project for a more detailed description. \end{bigspecs} @ Format commands are declared as an enumeration type [[Format_command]] using the names from the above list. The numbers assigned to the commands are only important for the implementation. <>= enum Format_command { null = 0, indent = 1, outdent = 2, opt0 = 3, opt1 = 4, opt2 = 5, opt3 = 6, opt4 = 7, opt5 = 8, opt6 = 9, opt7 = 10, opt8 = 11, opt9 = 12, backup = 13, break_space = 14, force = 15, big_force = 16, no_indent = 17, cancel = 18 }; @ As the format commands are declared as an enumeration type, they are represented by a number at run time. To nevertheless have access to the actual {\em name} of a format command there is an array of strings present from which the name of a format command can be won. So suppose [[fc]] is a format command, then % \begin{quote} [[Format_command_str[fc] ]]\par \end{quote} % is the name of [[fc]] as a string ([[char*]]). <>= extern char *Format_command_str[]; @ \begin{impls} The names of the format commands are stored in the following array. <>= char *Format_command_str[] = { "null", "indent", "outdent", "opt0", "opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", "opt8", "opt9", "backup", "break_space", "force", "big_force", "no_indent", "cancel" }; @ \end{impls} \section{Typesetter Dependence} As mentioned above, the interpretation of format commands by the output device (the typesetter) depends on the capabilities of this `machine'. For example, a simple matrix-dot line printer will have problems doing a \fmt{backup} or determining the place of a line break by itself, whereas a sophisticated formatting system like \TeX\ will be able to do all this and even more. It is clear, that the typesetter dependence starts on a level below the formatting commands. Indeed, formatting commands have been introduced specifically to have an abstraction of formatting requirements. So the typesetter dependence can be encapsulated within the [[Output]] class presented here. How is this done? In general, objects of the [[Output]] class are filters that interpret a stream of attributes and put them into a form that the typesetter can understand. We cannot hardcode this interpretation into the class, as this would inhibit a user from using several prettyprinters with different targets in a single program. Here object oriented approaches come in handy. We will think of typesetter dependent output objects as specializations of an `abstract' output. This maps to the idea of having an abstract base class [[Output]] and having one subclass per typesetter that we want as target. The specialized subclasses have all typesetter dependencies built in to them and the abstract base class does nothing else as dynamic dispatch. This module will present the abstract base class definition and will show by example how to build a specialized [[Output]] class. The example has \LaTeX\ as target typesetter. \section{Using the Output Class (Overview)} \begin{flushright} {\it Outputs output attributes.} \end{flushright} \noindent Here now is an overview of how to use [[Outputs]]. You need at least one output to output an attribute. Outputs have the interpretation of the format commands built in to them. However, as this is typesetter dependent. you will need to choose a specific subclass of the [[Output]] class. \begin{table} \begin{center} \leavevmode \begin{tabular}{llp{6cm}} [[Output(ostream&)]] & & constructor, sends all output to this object to the given [[ostream]] \\ [[~Output()]] & & destructor \\ [[do_output(char*)]] & [[void]] & output a string \\ [[do_output(Format_command)]] & [[void]] & output a format command \\ \end{tabular} \caption{Member functions of the [[Output]] class.} \label{tab:outputfunctions} \end{center} \end{table} Table \ref{tab:outputfunctions} lists the functions you can use on an output. So, if you want to create an output called [[outp]] that is connected to the output stream [[os]], then you should say something like this: % \begin{quote} [[Output outp(os);]] \end{quote} % The overloaded [[do_output]] member function does automatic interpretation of the format commands. So, if [[o]] is an output the command % \begin{quote} [[o.do_output(force);]] \end{quote} % will produce an interpretation of a \fmt{force} format command on the output stream connected to the output. The sequence % \begin{quote} [[o.do_output("some text");]] \end{quote} % will simply pass this string on to the same output stream. \subsection*{Debugging} Table \ref{tab:outputdebug} shows two special debug member functions that can be called on an output object. They make the format commands passed to the output object visible before they are interpreted: \begin{table} \begin{center} \leavevmode \begin{tabular}{llp{6cm}} [[debug_on()]] & [[void]] & start making format commands visible \\ [[debug_off()]] & [[void]] & end debug mode \\ \end{tabular} \caption{Special debug member functions of the [[Output]] class.} \label{tab:outputdebug} \end{center} \end{table} If you call [[debug_on]] on an output object it will output the name of the format command as string to the connected output stream. This name is encapsulated in angled brackets but this can be changed (see page \pageref{changedebugoutput}). The [[debug_off]] member function turns all this off again. \section{The Interface to the Output Class (Details)} Here at last is the final reference of the abstract base class. The private and protected members are only interesting for the implementation. <>= class Output { public: Output(ostream& ostr); virtual ~Output(); void do_output(char*); void do_output(Format_command); <> protected: <> private: <> }; @ \begin{impls} The output class is used to output attributes to an output stream. Attributes basicly are simple strings or format commands (that basicly are instructions for a typesetter). The information they contain is output by using the two [[do_output]] member functions. Strings are simply sent to the output stream. But format commands need a small overhead of interpretation. Also, the output produced by the format commands is typesetter dependent! \end{impls} It is important to note here that the output is buffered with one element of lookahead. This is necessary because of the interpretation performed on the format commands. You can only be sure that a format command has been output until you have destroyed the output object with the destructor or until you have output a string. @ You can switch on a debug mode as you use an output if you call the member function [[debug_on]]. If an output is in debug mode, it not only interprets format commands, but also prints out the names of the format commands to the [[ostream]] {\em before} they are interpreted. (This is important because some format commands never are actually output, like [[cancel]].) These names are surrounded by two strings [[bs]] (for ``beginning string'') and [[es]] (for ``ending string'') that you can pass on to [[debug_on]] as arguments. So if you are using \TeX\ you could switch on the debug option with \label{changedebugoutput} % \begin{quote} [[o.debug_on("% ","\n");]] \end{quote} % to make these names invisible for \TeX. Note that the contents of [[bs]] and [[es]] are copied. You can re-use the string pointers later if you wish. The maximum length of the beginning and ending delimiters is set to [[max_debug_del_size]]. If you pass on longer strings to [[debug_on]] they will be cut off after the given number of characters. <>= #define max_debug_del_size 10 @ The default setting for the [[debug_on]] member function is with [["["]] and [["]"]] as beginning and ending strings. You can switch off the debug mode with [[debug_off]]. <>= void debug_on(char *bs = "[", char *es = "]" ); /* turn on debug mode */ void debug_off(); /* get back to normal mode again */ @ \begin{impls} Whether the output is in debug mode is stored in the private member [[debug_mode]] that can be [[on]] or [[off]]. During debug mode, the names of the format commands are output as strings before they are interpreted. The names are surrounded by the two strings stored in the private members [[begin_string]] and [[end_string]]. <>= enum { /* are we debugging or not? */ yes, no } debug_mode; char begin_string[max_debug_del_size+1]; char end_string[max_debug_del_size+1]; @ So assuming that the format command that shall be interpreted next is stored in [[next_output]] and that [[os]] is the [[ostream]] connected to our output, every interpretation is preceded by the following text: <>= if (debug_mode==yes) { os << begin_string << Format_command_str[next_output] << end_string; } @ @ The [[debug_on]] member function turns the debug mode on. You can change the default values of the beginning and ending strings by passing string values to the function. The maximum length of these strings is [[max_debug_del_size]] as defined in the specification. The strings are copied and we make sure that the strings are terminated if the user passes on a long string to the function. <>= void Output::debug_on(char *bs, char *es) { strncpy(begin_string,bs, max_debug_del_size); begin_string[max_debug_del_size] = '\0'; strncpy(end_string,es, max_debug_del_size); end_string[max_debug_del_size] = '\0'; debug_mode=yes; } @ <>= #include @ The [[debug_off]] member function simply turns the debug mode off again. <>= void Output::debug_off() { debug_mode=no; } @ \end{impls} \begin{impls} Before we go further in the description of the implementation, we need to present the basic mechanism within each output. \subsection*{The Mechanism inside every Output} Outputting attributes through an output class object has to obey a set of two rules. % \begin{itemize} \item First, a continuous sequence of [[break_space]], [[force]] and/or [[big_force]] primitives will be transformed into a single command (the maximum of the given ones). \item Second, a [[cancel]] command cancels any [[break_space]], [[opt]], [[force]], or [[big_force]] that immediately precede or follow it and also cancels any [[backup]] command that follows it. \end{itemize} % It is beyond the scope of this document to explain the motivation behind these rules. The reader is referred to the main part of the documentation of the ``pretzel'' project, of which this text is only a small part. The transformation rules are implemented using a lookahead storage and a finite state machine. The lookahead is stored in the private member [[next_output]] and the finite state machine is implemented as a static table. The idea behind this choice is that the next element to be output to the output stream is a function of the last element and the newly read element. For example, if the last element was a [[force]] command and the newly read element is a string, we'll have to output the [[force]] and the [[string]] at once. However, if we have just recieved another [[force]] command, we won't send anything to the output stream, because of the first rule (and the fact that there might be some more [[force]]s coming \ldots). Note that because strings are always output directly, the lookahead only needs to be able to store the last format command. The lookahead [[next_output]] can be [[in_use]] or [[empty]] that is stored in [[next_output_type]]. If it is [[in_use]] there is a format command stored in it. Table \ref{tab:usenextoutput} summarizes the use of [[next_output_type]]. \begin{table} \begin{center} \leavevmode \begin{tabular}{|c|c|} \hline contents of [[next_output_type]] & state of lookahead \\ \hline [[in_use]] & stores a format command \\ [[empty]] & no format command in sight \\ \hline \end{tabular} \caption{Summary of possible values of [[next_output]].} \label{tab:usenextoutput} \end{center} \end{table} The protected members are only interesting for the implementation. <>= Format_command next_output; /* lookahead */ enum { /* type of the lookahead */ in_use, /* lookahead is in use */ empty /* lookahead is empty */ } next_output_type; ostream& os; /* this is where the output is going */ virtual void flush_output() = 0; /* outputs [[next_output]] to [[os]] */ @ @ I have put a few more member functions into the private section of the [[Output]] class to prevent \CPP\ from using any implicit casts or anything when dealing with outputs. <>= Output(); Output(const Output&); const Output& operator=(const Output&); @ As I have used an [[ostream]] type object above, I need to include the following header. It is the only header file needed in this specification. <
>= #include using namespace std; @ So let's handle a formality first: Here is the definition of the constructor of an output class object. A [[Output]] always has to be connected to an existing [[ostream]] during declaration. All information trespassing the output will go to this output stream. The output stream is stored in the private member [[os]]. Initially the lookahead is [[empty]] and the [[debug_mode]] is off. <>= Output::Output(ostream& ostr) : os (ostr) { next_output_type=empty; debug_mode=no; } @ @ A central part of the interpretation mechanism is a private member function called [[flush_output]]. It encapsulates (and performs) the interpretation of the format command that is momentarily stored in [[next_output]]. This function is invoked if the lookahead needs to be cleared. This is the case if for instance a string shall be output and there may still be an uniterpreted format command in the lookahead. If the lookahead is empty, [[flush_output]] does nothing, because it's task is to clear the lookahead (and this is already the case). The [[flush_output]] function is the only typesetter dependent part of the [[Output]] class and thus is declared virtual. We'll see what happens within [[flush_output]] later. Let's say that [[flush_output]] already works, then we can turn to the central public output routine [[do_output]] that is the basic interface to the outside world. [[do_output]] can take either a string or a format command as argument. Let's look at the ``string version'' first and then turn to the more interesting ``format command version''. @ The first version of [[do_output]] (for strings) simply outputs the string to the output stream [[os]]. If there happens to be a format command in the lookahead, this command is interpreted first with [[flush_output]]. (Again remember: If the lookahead is empty, [[flush_output]] doesn't do anything.) <>= void Output::do_output(char *s) { flush_output(); os << s; } @ \subsection{The Table Driven Output Routine} Outputting a format command is a little more complicated, because the lookahead has to be inspected before a format command is output. The lookahead storage [[next_output]] always holds the format command that is the hottest candidate to be interpreted next. However there are these ominous rules that have to be followed before a format command is actually output. These two rules are implemented with a table-driven finite state machine. Every time [[do_output]] is called with a format command and there still is a format command in the lookahead, the program looks up in a table, whether this special combination of commands triggers a rule. If so, the lookahead command is replaced with the result of the rule that was applied to the two initial commands. So if there is for instance a [[force]] command stored in the lookahead and [[do_output]] is called with a [[big_force]], the [[force]] will be replaced by the [[big_force]] as lookahead. So the [[do_output]] routine for format commands first inspects the state of the lookahead. If the lookahead is empty, then the incoming command becomes the lookahead. But if the lookahead is [[in_use]], the routine tries to apply a rule by looking into the internal table. But if there is no appropriate rule, it simply flushs the lookahead and takes the incoming token as new lookahead. <>= void Output::do_output(Format_command f) { if (next_output_type==empty) { next_output_type=in_use; next_output=f; /* take new command as lookahead */ return; } /* now try if a rule can be applied */ <> flush_output(); /* otherwise output the lookahead and store [[f]] */ next_output_type=in_use; next_output=f; } @ The rules stated in the above section are listed in table \ref{tab:rules}. The finite state machine operates with this table. The columns of the table represent the incoming token and the lines represent the lookahead command. So if there is a [[force]] in the lookahead and a [[big_force]] coming in, you will look into the sixth line at the seventh column to read what command results from the combination of those two primitives and should be written into the lookahead. Note that the only asymmetry in the table is due to the fact that a [[cancel]] cancels only [[backups]] that follow it (and not ones that precede it). If the table entry is only a star, then there is no rule that can be applied with these two tokens. I have used the following abbreviations: ind = [[indent]], out = [[outdent]], opt = [[opt0]],\dots,[[opt9]], bkp = [[backup]], bsp = [[break_space]], bigf = [[big_force]], nind = [[no_indent]]. \begin{table} \begin{center} \leavevmode \begin{tabular}{llllllllll} $\delta$ & ind & out & opt & bkp & bsp & force & bigf & nind & cancel \\ \hline indent & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ \\ outdent & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ \\ opt & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & cancel \\ backup & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ \\ bsp & $*$ & $*$ & $*$ & $*$ & bsp & force & bigf & $*$ & cancel \\ force & $*$ & $*$ & $*$ & $*$ & force & force & bigf & $*$ & cancel \\ bigf & $*$ & $*$ & $*$ & $*$ & bigf & bigf & bigf & $*$ & cancel \\ nind & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ & $*$ \\ cancel & $*$ & $*$ & cancel & cancel & cancel & cancel & cancel & $*$ & $*$ \\ \end{tabular} \caption{Table used to implement the two preprocessing rules with the [[Output]] class.} \label{tab:rules} \end{center} \end{table} @ Table \ref{tab:rules} is encoded in a two dimensional array [[delta]]. There are several more lines and columns with the implementation because the [[opt]] commands have to be listed in all and the [[null]] command takes a line and a column of it's own. The star from the table above is implemented as a [[null]] entry in the array. % hier habe ich in der Eile ein paar Fehler bei der Einrueckung gemacht! % man beachte die zusaetzliche Spalte! <>= static Format_command delta[cancel+1][cancel+1] = { /* this line is for the [[null]] command */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[indent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[outdent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[opt0]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt1]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt2]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt3]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt4]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt5]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt6]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt7]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt8]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt9]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[backup]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[break_space]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null,break_space,force,big_force,null, cancel}, /* now [[force]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, force, force,big_force,null, cancel}, /* now [[big_force]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, big_force,big_force,big_force,null, cancel}, /* now [[no_indent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[cancel]]: */ {null, null, null, cancel, cancel,cancel,cancel,cancel,cancel,cancel,cancel,cancel, cancel, cancel, cancel, cancel, cancel, null, null } }; @ To check whether a rule can be applied, you simply have to look up the appropriate entry in the table. <>= if (delta[next_output][f]!=null) { next_output=delta[next_output][f]; return; } @ If the last element of an attribute happens to be a format command it will stay in the lookahead of the output forever. This is why the destructor for the output object is explicitly defined here. Before an output object is destroyed, it's lookahead is flushed. <>= Output::~Output() { // synonym for flush_output(); // missing?! possibly in the subclasses! } @ \end{impls} \section{An Output for LaTeX} This section will give an example on how to build your own typesetter dependent output class. Here I will present a specialized output for \LaTeX. To build your own subclass for a specialized target look into the user manual or confer the file {\tt blankoutput.nw}. @ The first thing you have to do is to think of a good name. I`ll take [[Latex_cweb_output]], because the target is \LaTeX\ and the interpretation of format commands is based upon the macros of the \CWEB\ system. Now that we have a name, we can present the class declaration. <>= class Latex_cweb_output : public Output { public: Latex_cweb_output(ostream& ostr) : Output(ostr) {}; ~Latex_cweb_output() { flush_output(); }; private: void flush_output(); }; @ Yes, it`s as simple as that. Experienced readers will have noticed that only the [[flush_output]] routine was a virtual function and indeed, it is this single function that encapsulates the whole translation. So the next thing you have to do is to define the function [[flush_output]] in an implemenation file. As the only things that change in different implementations are the translations of the format commands, there is a special file in which you only have to replace preprocessor macro strings to do this. @ To use the LaTeX output, you`ll have to build a prettyprinter with pretzel and specify [[Latex_cweb_output]] as output class to use. The prettyprinted code will have special macros inserted into the output that are defined in {\tt pretzel-latex.sty}. Now you can use a new environment called {\tt ppcode}. Inbetween this environment the code will be formatted nicely. \begin{impls} As part of the implementation, here's an explanation how the typesetter dependent parts of [[Output]] subclasses should work. Essentially this is an explanation of an example implementation of the virtual [[flush_output]] routine. @ Here`s the frame of [[flush_output]]. It will always be called when the lookahead needs to be cleared. If the lookahead is empty, we don`t need to do anything. <>= void Latex_cweb_output::flush_output() { if (next_output_type==empty) return; /* otherwise: */ <> next_output_type=empty; } @ Ok, so now let's turn to the part, where format commands are actually interpreted. Suppose the next format command to be interpreted is stored in [[next_output]]; the only thing to do now is to have a giant switch inspecting [[next_output]]. Every case in this switch outputs the corresponding code for this case to the [[ostream os]] that is connected to our output class object. <>= <> switch (next_output) { <> default: <> break; }; @ This shouldn't (can't) happen. <>= cerr << endl << "Unknown format command detected! Something's wrong here." << endl << endl; exit(EXIT_FAILURE); @ To use [[exit]], we have to include this: <>= #include @ And since some (really old) operating systems don't have the common [[EXIT_FAILURE]] and [[EXIT_SUCCESS]] macros defined (in [[stdlib.h]]), we'll define them here. (Introduced for Denis Roegel, \verb"roegel@lorraine.loria.fr".) <
>= #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif @ Now we will start to scan the cases in the big switch. The easiest command is surely the [[null]] command. It has an ``empty'' interpretation. <>= case null: /* do nothing */ break; @ The next two cases are [[indent]] and [[outdent]]. They correspond to the {\tt pretzel-latex} macros \verb+\pretzelindent+ and \verb+\pretzeloutdent+. <>= case indent: os << "\\pretzelindent{}"; break; case outdent: os << "\\pretzeloutdent{}"; break; @ The next cases handle the 10 instances of the [[opt]] command. The [[opt]] command is turned into the macro \verb+\pretzelopt+ with the number of [[opt]] (like 6 in [[opt6]]) as an additional digit. <>= case opt0: os << "\\pretzelopt0{}"; break; case opt1: os << "\\pretzelopt1{}"; break; case opt2: os << "\\pretzelopt2{}"; break; case opt3: os << "\\pretzelopt3{}"; break; case opt4: os << "\\pretzelopt4{}"; break; case opt5: os << "\\pretzelopt5{}"; break; case opt6: os << "\\pretzelopt6{}"; break; case opt7: os << "\\pretzelopt7{}"; break; case opt8: os << "\\pretzelopt8{}"; break; case opt9: os << "\\pretzelopt9{}"; break; @ The [[backup]] command corresponds to \verb+\pretzelbackup+ in {\tt pretzel-latex.sty}. <>= case backup: os << "\\pretzelbackup{}"; break; @ [[break_space]] is a \verb+\pretzelbreakspace+ \dots <>= case break_space: os << "\\pretzelbreakspace{}"; break; @ Here is the [[force]] command \dots <>= case force: os << "\\pretzelforce{}"; break; @ \dots and here is the [[big_force]] command. <>= case big_force: os << "\\pretzelbigforce{}"; break; @ Here is [[no_indent]]: <>= case no_indent: os << "\\pretzelnoindent{}"; break; @ And finally we arrive at the [[cancel]] command. In the actual output, [[cancel]] is interpreted like [[null]]. This is due to the fact that [[cancel]] influences the interpretation before the commands are actually output to the [[ostream]]. <>= case cancel: /* do nothing */ break; @ \end{impls} \section*{Identifier Index} \begin{multicols}{2} \nowebindex \end{multicols} \end{document} % % $Log: output.nw,v $ % Revision 2.1 1997/07/08 19:00:45 gaertner % Bug fix proposed by Holger Uhr: cancel cancels big_force now. % % Revision 2.0 1996/12/16 17:26:59 gaertner % *** empty log message *** % % Revision 1.1 1996/03/13 11:28:37 gaertner % Initial revision % % pretzel-2.0n-2/output/index.list0000644000000000000000000000067206360716216015433 0ustar rootrootthis directory & the Output class README & more information Makefile & the makefile asciioutput.dvi & an explanation of the asciioutput class asciioutput.nw & noweb source of the asciioutput class blankoutput.nw & a template output for new output subclasses output-specs.dvi & specifications of the output class output.nw & source of the output class outtest.nw & tester for the output class test.output.correct & needed for regression test pretzel-2.0n-2/output/README0000644000000000000000000000103506255303070014272 0ustar rootrootREADME for the output subdirectory of Pretzel It contains the following files: README this file Makefile asciioutput.dvi.gz an explanation of the asciioutput class asciioutput.nw source of the asciioutput class blankoutput.nw a template output for new output subclasses output-specs.dvi.gz specifications of the output class output.nw source of the output class outtest.nw tester for the output class test.output.correct needed for regression test If you are planning to build a new type of Output, look into blankoutput.nw pretzel-2.0n-2/output/index.html0000644000000000000000000000262506360716224015423 0ustar rootroot Index file for directory "pretzel/output" of Pretzel distribution

Index file for directory "pretzel/output" of Pretzel distribution

Files and directories are:

this directory

    the Output class
README
    more information
Makefile
    the makefile
asciioutput.dvi
    an explanation of the asciioutput class
asciioutput.nw
    noweb source of the asciioutput class
blankoutput.nw
    a template output for new output subclasses
output-specs.dvi
    specifications of the output class
output.nw
    source of the output class
outtest.nw
    tester for the output class
test.output.correct
    needed for regression test

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 16:13:41 MESZ 1997 pretzel-2.0n-2/output/dr0000644000000000000000000001534006465645123013761 0ustar rootroot#line 107 "output.nw" /* this is the implementation of the Output class */ #include"output.h" /* include the own header */ #line 543 "output.nw" #include #line 1035 "output.nw" #include #line 269 "output.nw" char *Format_command_str[] = { "null", "indent", "outdent", "opt0", "opt1", "opt2", "opt3", "opt4", "opt5", "opt6", "opt7", "opt8", "opt9", "backup", "break_space", "force", "big_force", "no_indent", "cancel" }; #line 815 "output.nw" static Format_command delta[cancel+1][cancel+1] = { /* this line is for the [[null]] command */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[indent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[outdent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[opt0]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt1]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt2]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt3]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt4]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt5]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt6]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt7]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt8]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[opt9]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, cancel}, /* now [[backup]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[break_space]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null,break_space,force,big_force,null, cancel}, /* now [[force]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, force, force,big_force,null, cancel}, /* now [[big_force]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, big_force,big_force,big_force,null, cancel}, /* now [[no_indent]]: */ {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null}, /* now [[cancel]]: */ {null, null, null, cancel, cancel,cancel,cancel,cancel,cancel,cancel,cancel,cancel, cancel, cancel, cancel, cancel, cancel, null, null } }; #line 531 "output.nw" void Output::debug_on(char *bs, char *es) { strncpy(begin_string,bs, max_debug_del_size); begin_string[max_debug_del_size] = '\0'; strncpy(end_string,es, max_debug_del_size); end_string[max_debug_del_size] = '\0'; debug_mode=yes; } #line 549 "output.nw" void Output::debug_off() { debug_mode=no; } #line 662 "output.nw" Output::Output(ostream& ostr) : os (ostr) { next_output_type=empty; debug_mode=no; } #line 696 "output.nw" void Output::do_output(char *s) { flush_output(); os << s; } #line 733 "output.nw" void Output::do_output(Format_command f) { if (next_output_type==empty) { next_output_type=in_use; next_output=f; /* take new command as lookahead */ return; } /* now try if a rule can be applied */ #line 920 "output.nw" if (delta[next_output][f]!=null) { next_output=delta[next_output][f]; return; } #line 744 "output.nw" flush_output(); /* otherwise output the lookahead and store [[f]] */ next_output_type=in_use; next_output=f; } #line 932 "output.nw" Output::~Output() { // synonym for flush_output(); // missing?! possibly in the subclasses! } #line 1000 "output.nw" void Latex_cweb_output::flush_output() { if (next_output_type==empty) return; /* otherwise: */ #line 517 "output.nw" if (debug_mode==yes) { os << begin_string << Format_command_str[next_output] << end_string; } #line 1018 "output.nw" switch (next_output) { #line 1042 "output.nw" case null: /* do nothing */ break; #line 1048 "output.nw" case indent: os << "\\pretzelindent{}"; break; case outdent: os << "\\pretzeloutdent{}"; break; #line 1056 "output.nw" case opt0: os << "\\pretzelopt0{}"; break; case opt1: os << "\\pretzelopt1{}"; break; case opt2: os << "\\pretzelopt2{}"; break; case opt3: os << "\\pretzelopt3{}"; break; case opt4: os << "\\pretzelopt4{}"; break; case opt5: os << "\\pretzelopt5{}"; break; case opt6: os << "\\pretzelopt6{}"; break; case opt7: os << "\\pretzelopt7{}"; break; case opt8: os << "\\pretzelopt8{}"; break; case opt9: os << "\\pretzelopt9{}"; break; #line 1071 "output.nw" case backup: os << "\\pretzelbackup{}"; break; #line 1076 "output.nw" case break_space: os << "\\pretzelbreakspace{}"; break; #line 1081 "output.nw" case force: os << "\\pretzelforce{}"; break; #line 1086 "output.nw" case big_force: os << "\\pretzelbigforce{}"; break; #line 1091 "output.nw" case no_indent: os << "\\pretzelnoindent{}"; break; #line 1099 "output.nw" case cancel: /* do nothing */ break; #line 1021 "output.nw" default: #line 1027 "output.nw" cerr << endl << "Unknown format command detected! Something's wrong here." << endl << endl; exit(EXIT_FAILURE); #line 1021 "output.nw" break; }; #line 1006 "output.nw" next_output_type=empty; } pretzel-2.0n-2/output/asciioutput.nw0000644000000000000000000002541306467622714016355 0ustar rootroot% This is a file written using noweb % % $Id: asciioutput.nw,v 1.1 1996/03/13 11:30:06 gaertner Exp $ % \documentclass{article} \usepackage{a4,pretzeldoc,version,noweb} \begin{document} \includeversion{bigspecs} \includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification %\excludeversion{impls}% without implementation \title{[[Ascii_terminal_output]]\thanks{This file is based on a template for a subclass of the [[Output]] class written by Felix G\"artner.} \\ An [[Output]] Subclass for Screen or Line Printer} \author{Felix G\"artner} % put your own name here \maketitle \begin{abstract} % fill in the abstract at the places marked XXX or write your own This file contains a subclass of the [[Output]] class called [[Ascii_terminal_output]]. It can be used to create a prettyprinter for a normal terminal screen. It belongs to a framework supplied by the ``pretzel'' prettyprinter generator. \end{abstract} \tableofcontents % Fill in the places marked XXX or write your own text. \section{Introduction} This text describes the specification \begin{impls}and implementation\end{impls} for a new subclass of the \CPP\ [[Output]] class. It specializes on a simple ASCII terminal or line printer output device. It is a contribution to the ``pretzel'' system, a prettyprinter generator written by Felix G\"artner (\verb+theedge@rbg.informatik.th-darmstadt.de+). For more examples of this kind of thing consult the files {\tt output.nw} and {\tt blankoutput.nw} included in the pretzel distribution. @ Here's the frame of the header for the new subclass. <

>= #ifndef ASCIIOUTPUT_H #define ASCIIOUTPUT_H #include "output.h" /* base class defined in here */ <> <> #endif @ \begin{impls} Here's the framework of the implementation. <>= #include "asciioutput.h" <
> <> <> <> @ \end{impls} In the following section of this document we will explain the purpose of this subclass and the results obtained when using it together with pretzel. This is the interface of the class. \begin{impls}In the following section we will focus on the details of the implementation of the new subclass.\end{impls} First of all, this is what the name of the subclass will look like in the program: <>= #define Ascii_terminal_output_SUBCLASS_NAME Ascii_terminal_output @ \section{Interface and Use} A terminal or simple line printer is pretty dumb and naturally cannot compete with such advanced typesetting systems like \TeX. But sometimes prettyprinted output to a screen or an ASCII line printer is required. This class implements this kind of stuff. To actually build a prettyprinter of this kind you'll have to extract a header and implementation file from this text, include it in the prettyprinter specification and specify this subclass as argument to the actual prettyprinter object. [Example missing] @ The actual declaration of the new subclass is pretty simple, once we've defined the name. <>= class Ascii_terminal_output_SUBCLASS_NAME : public Output { public: Ascii_terminal_output_SUBCLASS_NAME(ostream& ostr) : Output(ostr) {}; ~Ascii_terminal_output_SUBCLASS_NAME() { flush_output(); }; private: void flush_output(); }; @ Yes, it`s as simple as that. The only thing needed to do now is think about the actions that have to be done when interpreting format commands and implement them within the [[flush_output]] routine, which is a pure virtual function inside the [[Output]] base class. The main parts of this routine are always identical. The only differences are the different things done when format commands are interpreted. \subsection{Aspects of ASCII Terminal Output} We'll keep the ideas implemented here simple. The format commands that will be implemented will be % \begin{itemize} \item [[indent]], [[outdent]] \item [[force]], [[big_force]] \end{itemize} % This means that no line breaking mechanism is implemented at the moment (although this would be possible) and the special commands [[backup]] and [[no_indent]] will not come out correctly. @ The amount of indentation is defined here (two blanks at present). <>= #define Ascii_terminal_output_INDENTATION_STRING " " @ \begin{impls} \section{Implementation} As part of the implementation, here's an explanation how the typesetter dependent parts of the new subclass work. Essentially this is an explanation of an example implementation of the virtual [[flush_output]] routine. @ A lot of things can be defined here using the macro definitions here. Here we specify the strings output to the internal output steam when the corresponding format commands are interpreted. <>= #define Ascii_terminal_output_NULL_OUTPUT_STRING "" #define Ascii_terminal_output_INDENT_OUTPUT_STRING "" #define Ascii_terminal_output_OUTDENT_OUTPUT_STRING "" #define Ascii_terminal_output_OPT0_OUTPUT_STRING "" #define Ascii_terminal_output_OPT1_OUTPUT_STRING "" #define Ascii_terminal_output_OPT2_OUTPUT_STRING "" #define Ascii_terminal_output_OPT3_OUTPUT_STRING "" #define Ascii_terminal_output_OPT4_OUTPUT_STRING "" #define Ascii_terminal_output_OPT5_OUTPUT_STRING "" #define Ascii_terminal_output_OPT6_OUTPUT_STRING "" #define Ascii_terminal_output_OPT7_OUTPUT_STRING "" #define Ascii_terminal_output_OPT8_OUTPUT_STRING "" #define Ascii_terminal_output_OPT9_OUTPUT_STRING "" #define Ascii_terminal_output_BACKUP_OUTPUT_STRING "" #define Ascii_terminal_output_BREAKSPACE_OUTPUT_STRING "" #define Ascii_terminal_output_FORCE_OUTPUT_STRING "\n" #define Ascii_terminal_output_BIGFORCE_OUTPUT_STRING "\n\n" #define Ascii_terminal_output_NOINDENT_OUTPUT_STRING "" #define Ascii_terminal_output_CANCEL_OUTPUT_STRING "" @ Here`s the frame of [[flush_output]]. It will always be called when the lookahead needs to be cleared. If the lookahead is empty, we don`t need to do anything. <>= void Ascii_terminal_output_SUBCLASS_NAME::flush_output() { if (next_output_type==empty) return; /* otherwise: */ <> next_output_type=empty; } @ Ok, so now let's turn to the part, where format commands are actually interpreted. Suppose the next format command to be interpreted is stored in [[next_output]]; the only thing to do now is to have a giant switch inspecting [[next_output]]. Every case in this switch outputs the corresponding code for this case to the [[ostream os]] that is connected to our output class object. <>= <> switch (next_output) { <> default: <> break; }; @ <>= if (debug_mode==yes) { os << begin_string << Format_command_str[next_output] << end_string; } @ This shouldn't (can't) happen. <>= cerr << endl << "Unknown format command detected! Something's wrong here." << endl << endl; exit(EXIT_FAILURE); @ To use [[exit]], we have to include this: <
>= #include @ And since some (really old) operating systems don't have the common [[EXIT_FAILURE]] and [[EXIT_SUCCESS]] macros defined (in [[stdlib.h]]), we'll define them here. <
>= #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif @ Now we will start to scan the cases in the big switch. The actions performed are essentially the output of a special string defined in the interface above. However, as an ASCII terminal is quite dumb, we need to explicitly code some parts (like managing indentation). \subsection{Implementing [[indent]] and [[outdent]]} We need an internal counter to hold the current amount of indentation. Here's a static variable for this purpose. <>= static int ind = 0; @ <>= case indent: os << Ascii_terminal_output_INDENT_OUTPUT_STRING ; ind++; break; case outdent: os << Ascii_terminal_output_OUTDENT_OUTPUT_STRING ; ind--; break; @ The [[force]] and [[big_force]] commands break the line and add as much whitespace as required by [[ind]]. <>= case force: os << Ascii_terminal_output_FORCE_OUTPUT_STRING ; { for (int i=0; i< ind; i++) { os << Ascii_terminal_output_INDENTATION_STRING ; } } break; case big_force: os << Ascii_terminal_output_BIGFORCE_OUTPUT_STRING ; { for (int i=0; i< ind; i++) { os << Ascii_terminal_output_INDENTATION_STRING ; } } break; @ \subsection{Line Breaking} The format commands concering line breaking are not implemented. <>= case opt0: os << Ascii_terminal_output_OPT0_OUTPUT_STRING ; break; case opt1: os << Ascii_terminal_output_OPT1_OUTPUT_STRING ; break; case opt2: os << Ascii_terminal_output_OPT2_OUTPUT_STRING ; break; case opt3: os << Ascii_terminal_output_OPT3_OUTPUT_STRING ; break; case opt4: os << Ascii_terminal_output_OPT4_OUTPUT_STRING ; break; case opt5: os << Ascii_terminal_output_OPT5_OUTPUT_STRING ; break; case opt6: os << Ascii_terminal_output_OPT6_OUTPUT_STRING ; break; case opt7: os << Ascii_terminal_output_OPT7_OUTPUT_STRING ; break; case opt8: os << Ascii_terminal_output_OPT8_OUTPUT_STRING ; break; case opt9: os << Ascii_terminal_output_OPT9_OUTPUT_STRING ; break; case break_space: os << Ascii_terminal_output_BREAKSPACE_OUTPUT_STRING ; break; @ \subsection{Going Back} The [[backup]] and [[no_indent]] are also not implemented. <>= case backup: os << Ascii_terminal_output_BACKUP_OUTPUT_STRING ; break; case no_indent: os << Ascii_terminal_output_NOINDENT_OUTPUT_STRING ; break; @ \subsection{The [[null]] and [[cancel]] commands} <>= case null: os << Ascii_terminal_output_NULL_OUTPUT_STRING ; break; case cancel: os << Ascii_terminal_output_CANCEL_OUTPUT_STRING ; break; @ \end{impls} \end{document} % % $Log: asciioutput.nw,v $ % Revision 1.1 1996/03/13 11:30:06 gaertner % Initial revision % % pretzel-2.0n-2/output/Makefile0000644000000000000000000001261206474246753015076 0ustar rootroot# $Id: Makefile,v 1.7 1996/03/13 11:31:26 gaertner Exp gaertner $ # ---------------------------------------------------------------------- # # Makefile for Output class and testers. # # # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = g++ # de-comment this if you want a debug version: #DBVERSION = -D XXX # flags for cc: CFLAGS = -I../include -L.. -lpretzel -g # Groups of files: # all noweb sources NOWEBS = output.nw outtest.nw blankoutput.nw asciioutput.nw # root chunk name of headers HEADERCHUNK = header # root chunk name of implementation IMPLEMENTATIONCHUNK = implementation # all `WEB' sources (old) #WEBS = output.spc output.w outtest.w # all other program WEB sources (old) #ETCWEBS = # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = Makefile test.output.correct # name of the distribution package DISTNAME = output # Which program to make by default: PROG = outtest # objects of this program: OBJS = outtest.o output.o asciioutput.o # objects to be released: RELOBJS = output.o asciioutput.o # RELHEADERS = output.h asciioutput.h # C sources of this program: CSRCES = outtest.c output.c asciioutput.c # these files are crap and may be deleted if we say `make clean' REST = dvidriv.prt output.aux output.idx output.log output.scn \ output.tex output.toc outtest.aux outtest.idx \ outtest.log outtest.scn outtest.tex outtest.toc \ outtest.dvi output.dvi test.output \ asciioutput.aux asciioutput.idx asciioutput.log \ asciioutput.scn asciioutput.tex asciioutput.toc # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # You probably don't need to change anything from here: # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = output.h asciioutput.h # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) # these are all header files produced from WEBs that may appear ALLHEADERS = $(HEADERS) # these are all the executables that could be produced ALLPROGS = outtest # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle NOTANGLE= notangle NOWEAVE = noweave TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex -d #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = tex-it latex # ---------------------------------------------------------------------- .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h # overall rules: .nw.tex: $(NOWEAVE) -delay -index $*.nw > $*.tex .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .nw.h: $(NOTANGLE) -L -R$(HEADERCHUNK) $*.nw > $*.h .nw.c: $(NOTANGLE) -L -R$(IMPLEMENTATIONCHUNK) $*.nw > $*.c .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) $(CCFLAGS) -c $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) $(CC) $(OBJECTS) $(CCFLAGS) -o $@ $(OBJS): $(HEADERS) $(CSRCES) # make a copy of the specs specs: output.spc $(CWEAVE) output.spc - output.tex $(LATEX) output.tex # list all source code: print: # apply lint to all C sources: lint: # regression: regression: $(PROG) outtest > test.output if diff test.output test.output.correct; \ then echo "Regression test is fine."; \ else echo "Regression test failed."; \ fi # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(REST) # remove everything that doesn't belong to original source: clobber: clean $(REMOVE) $(ALLPROGS) # bundle source files together into an archive: #bundle: # tar cf $(DISTNAME).tar \ # $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # copy executables into PATH directories, et al. #install: # make a release release: $(RELHEADERS) $(RELOBJS) cp $(RELHEADERS) ../include ar vrus ../libpretzel.a $(RELOBJS) # ====================================================================== # # $Log: Makefile,v $ # Revision 1.7 1996/03/13 11:31:26 gaertner # Updated for use of new noweb ports of output. # # Revision 1.6 1995/04/26 17:35:37 gaertner # You can make specs now to get a printed output of the # specifications. # The release and compile use lpretzel library. # You can make a regression test now. # # Revision 1.5 1994/10/31 19:01:59 gaertner # Now make bundle creates output.tar. # # Revision 1.4 1994/10/24 16:48:00 gaertner # Now outtest.o isn't released anymore. # # Revision 1.3 1994/10/07 07:48:22 gaertner # `make clean' will remove LaTeX intermediate products now. # # Revision 1.2 1994/10/05 18:43:11 gaertner # First revision using the Makefile template. # # pretzel-2.0n-2/output/output-specs.dvi0000644000000000000000000005113006255300754016600 0ustar rootroot÷ƒ’À;è TeX output 1996.12.16:1807‹ÿÿÿÿ É ýC Ÿ ý®’Ö<óDÓítG®G®cmr17ºThe–7tOutput“ClassŽŸ’¹Þ„óX«Q cmr12»F‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸˆ‹’«ßúDecem¬rbSŽer–ê¨16,“1996ŽŸ$’È Ãót ‰: cmbx9ÅAbstractŽŸ¬Ñ‘NŸ¨óo´‹Ç cmr9ÄThis–Ktext“con¾9tains“a“description“of“a“new“óŒ-ø cmcsc10ÆCŸÿÄ++Ž‘¯class“called“óߤN cmtt9ÇOutputÄ.‘¿%Thisޤ ‘@¿®class–Æ»is“used“to“proAÇcess“ob‘ƒŽjects“that“conš¾9tain“prett˜yprin˜ting“information“(in-Ž¡‘@¿®stances––²of“the“ÇAttribute“Äclass)“and“turn“them“inš¾9to“screen“or“t˜ypAÇesetter“de-Ž¡‘@¿®pAÇendenš¾9t–rxoutput.‘3ÜAlso,‘ÉÀthe“text“presen˜ts“a“w˜a˜y‘ÿ:«,‘ÉÀho˜w“to“create“spAÇecializedŽ¡‘@¿®subAÇclasses–Tof“ÇOutput“Äto“adapt“to“di eren¾9t“output“targets.Ž©!Ä‘'¿¬óÂÖN ff cmbx12ÉCon•ŒÌten“tsޤ‘'¿¬óò"V cmbx10Ê1Ž‘6¿­In®9troQÇduction–ÕTto“the“Output“Class’¬™!1ŽŽ¡‘'¿¬2Ž‘6¿­F‘ÿ «ormat‘ÕTcommands’÷lñ3ŽŽ¡‘'¿¬3Ž‘6¿­T®9yp•QÇesetter‘ÕTDep“endence’Ýd5ŽŽ¡‘'¿¬4Ž‘6¿­Using–ÕTthe“Output“Class“(Ov®9erview)’¡Su5ŽŽ¡‘'¿¬5Ž‘6¿­The–ÕTIn®9terface“to“the“Output“Class“(Details)‘xA¾6ŽŽ¡‘'¿¬6Ž‘6¿­An–ÕTOutput“for“LaT‘ÿ «eX’åÀÞ7ŽŽ¦‘'¿¬É1Ž‘@ wInŒÌtros3duction–ffto“the“Output“ClassŽŸç‘'¿¬óKñ`y cmr10²This–Æ·text“con¸ãtains“the“spGeci cations‘nfor“a“new“ó Œ-ø cmcsc10ËCŸÿ²++Ž‘Tóclass“called“óßê cmmi10µn²,‘UUµn–Ǹ2“f²0µ;˜:˜:˜:Ž‘ÿ÷;˜²9¸gŽ’œ‹²denotes–van“optional“line“break“with“the“con•¸ãtin“uationŽ¡’œ‹line–­Vinden¸ãted“a“litte“with“respGect“to“the“normal“start-Ž¡’œ‹ing–§pšGosition.‘fàThis“line“break“will“score“a“p˜enalt¸ãy“ofŽ¡’œ‹10µn².ŽŽŽŽŸ0‘8º)Ìb‘ÿ}'ackupŽ’œ‹²denotes–UUa“small“bac¸ãkspaceŽŽŽŽ¡‘8º)Ìbig‘‰ffŽ‘®for–ÿ}'c“eŽ’œ‹²forces–UUa“line“break“and“inserts“a“little“extra“spaceŽŽŽŽ¡‘8º)Ìno‘‰ffŽ‘®indentŽ’œ‹²causes–UUthe“curren¸ãt“line“to“bGe“output“ ushleftŽŽŽŽ¡‘8º)Ìc–ÿ}'anc“elŽ’œ‹²obliterates–W'an¸ãy“Ìbr–ÿ}'e“ak‘‰ffŽ›®sp“ac“e²,–×›Ìopt²,“Ìfor–ÿ}'c“e–W'²or“Ìbig‘‰ffŽ˜for–ÿ}'c“eŽ¡’œ‹²command–ÙÇthat“immediatly“precedes“or“follo¸ãws“it“andŽ¡’œ‹also–UUcancels“anš¸ãy“Ìb‘ÿ}'ackup“²command“that“follo˜ws“it.ŽŽŽŽŽŽŽŸiqÇ‘KÓT‘ÿ*ªable–UU1:‘qÇList“of“format“commands“suppGorted“b¸ãy“the“¹Output“²class.ŽŽŽŸ%’‘'¿¬É2Ž‘@ wF‘þ¦format‘ffcommandsŽŸç‘'¿¬²F‘ÿ*ªormat–'Îcommands“are“abstract“instructions“for“a“tš¸ãypGesetter“or“an˜y“other“outputޤ ‘'¿¬device.Ÿü^ÿóÙ“ Rcmr7±1ŽŽ‘ ‘²F‘ÿ*ªor–6Lexample“they“tell“the“t¸ãypGesetter“to“force“a“line“break,‘n‰to“add“someŽ¡‘'¿¬space–Ùto“the“currenš¸ãt“amoun˜t“of“inden˜tation“or“to“bac˜k“up“a“little.‘H]They“are“abstractŽ¡‘'¿¬in–ù4sucš¸ãh“a“w˜a˜y“that“they“can“bGe“in˜terpreted“di eren˜tly“depGending“on“the“capabilitiesŽ¡‘'¿¬of–§ûthe“t¸ãypGesetter“and“the“taste“of“the“user“who“is“using“it.‘i¸F‘ÿ*ªormat“commands“areŽ¡‘'¿¬inš¸ãtermixed–Æáwith“the“prett˜yprin˜ted“source“coGde“text“in“a“w˜a˜y“spGeci ed“b˜y“the“userŽ¡‘'¿¬(using–ˆÖan“attribute“grammar).‘-See“table“1“for“a“complete“list“of“all“suppGorted“formatŽ¡‘'¿¬commands.‘èAs–Òis“shoš¸ãwn“in“the“main“part“of“the“pro‘Ž8ject“doGcumen˜tation,‘ñLthey“areŽ¡‘'¿¬sucienš¸ãt–‹™to“format“all“desired“features“of“toGda˜y's“programming“languages.‘”TheŽ¡‘'¿¬spGecial›x¬w•¸ãa“y˜in˜whic“h˜to˜use˜them˜is˜again˜describ•Ged˜in˜the˜main˜do“cumen¸ãtation˜ofŽ¡‘'¿¬this›UUpro‘Ž8ject.‘ãŽHo•¸ãw“ev“er˜I˜will˜giv“e˜a˜v“ery˜short˜example˜here.Ž¡‘6¿¬T‘ÿ*ªo–pŒgivš¸ãe“y˜ou“a“fain˜t“idea“of“ho˜w“these“format“commands“w˜ork“here's“a“smallŽ¡‘'¿¬example–UUthat“in¸ãtroGduce“the“¹indent²,“¹outdent“²and“¹force“²commands:ŽŸÉd‘6¿¬Sa•¸ãy›zVw“e˜w“an“t˜to˜format˜an˜ÊifŽ‘ /©²-ÊthenŽ‘ÿ¤²construct˜in˜ËP‘ÿ ascal˜²and˜w“e˜w“an“t˜to˜inden“tŽ¡‘'¿¬the–w conditional“part“of“it“a“little.‘ÖåT‘ÿ*ªo“ac•¸ãhiev“e–w this“yš¸ãou“w˜ould“ha˜v˜e“to“insert“theŽ¡‘'¿¬format–UUcommands“inš¸ãto“the“source“text“as“follo˜ws:ޤîö‘1¿­¹if–?ýa>0“then“ÌindentŽ‘&Êôfor–ÿ}'c“eŽ‘A]½¹begin“abs“:=“1“end;“ÌoutdentŽŽ¡‘'¿¬²The–UUprevious“text“wš¸ãould“yield“something“lik˜e“this:Ž¡‘1¿­ÊifŽ‘;ÊUµa–Ç>“²0‘UUÊthenŽŽ¤ ‘;¿®bQÇeginŽ‘ZdúÌabsŽ‘kÊú²:=ŽŽ‘y M1‘UUÊendŽ‘aÁ²;Ž¡Ÿîö‘'¿¬This–|ýexample“shoš¸ãws“nicely“that“ÌindentŽ‘%Dô²and“ÌoutdentŽ‘*ac²only“tak˜e“e ect“after“a“lineŽ¡‘'¿¬break,‘íŸe.g.–Ó²they“determine“the“indenš¸ãtation“of“the“follo˜wing“line.‘F‘This“is“useful“if“y˜ouŽ¡‘'¿¬sometimes›­w•¸ãan“t˜a˜line˜break˜and˜other˜times˜y“ou˜don't.‘9´F‘ÿ*ªor˜example˜y“ou˜could˜onlyŽ¡‘'¿¬w•¸ãan“t–Nùa“line“break“in“the“previous“example“if“there“are“ÊbQÇeginŽ‘!íé²and“ÊendŽ‘ª^²k•¸ãeyw“ords‘NùinŽ¡‘'¿¬the–%source“coGde.‘É7If“they“are“missing“yš¸ãou“migh˜t“w˜an˜t“to“ha˜v˜e“the“formatting“lik˜eŽ¡‘'¿¬this:Ž‘'¿¬Ÿù/‰ff‰¬Ÿ J=‘ "5Ÿý-:ó¹Aa¨cmr6½1ŽŽŽ‘LܼY‘ÿJªou–sÉcan“use“a“markup“formatter“likšÃŽe“T‘þ•AŸ¸ãEŽ‘MX“or“a“simple“line“prin˜ter,‘‡Lwhic˜h“of“course“cannot“tak˜eޤ €on–R~things“likšÃŽe“automatic“line“and“page“breaks,‘qÈetc.‘>“In“the“follo˜wing“text“I‘R^will“therefore“alw˜a˜ysŽ¡refer–ÕXto“the“output“device“as“the“tÃŽyp“²0‘UUÊthenŽ‘/øÌabsŽ‘.•ø²:=ŽŽ‘;ëK1;ޤ Ÿ‘'¿¬The–ûßonly“thing“yš¸ãou“ha˜v˜e“to“do“is“Ìnot“²to“insert“a“Ìfor–ÿ}'c“eŽ‘N«².‘SõThis“lea˜v˜es“y˜ou“free“to“insertŽ¡‘'¿¬ÌindentŽ‘D ¦²s–·Dand“ÌoutdentŽ‘%­²s“automatically“bšGefore“and“b˜ehind“the“conditional“part“of“theŽ¡‘'¿¬construct,‘úas–y is“usefull“during“automatic“parsing“of“this“small“example.‘ÜîAgain“y¸ãouŽ¡‘'¿¬mš¸ãust–×sconfer“the“main“doGcumen˜tation“of“this“pro‘Ž8ject“for“a“more“detailed“description.Ž¡‘'¿¬F‘ÿ*ªormat–ö4commands“are“declared“as“an“enš¸ãumeration“t˜ypGe“¹Format_command“²usingŽ¡‘'¿¬the–î»names“from“the“abšGo•¸ãv“e–î»list.‘=úThe“n•¸ãum“b˜ers–î»assigned“to“the“commands“are“onlyŽ¡‘'¿¬impGortanš¸ãt–UUfor“the“implemen˜tation.Ž©‘ ‘@¼4aŽ‘'¿¬¸hÌDe nition–“çof“format“c‘ÿ}'ommands“¼4a¸iŽ’Ä—§Ž¡‘1¿¬¹enum–?ýFormat_command“{Ž¡‘F¿ null‘)ÿè=‘?ý0,Ž¡‘F¿ indent‘î=‘?ý1,Ž¡‘F¿ outdent‘?ñ=‘?ý2,Ž¡‘F¿ opt0‘)ÿè=‘?ý3,Ž¡‘F¿ opt1‘)ÿè=‘?ý4,Ž¡‘F¿ opt2‘)ÿè=‘?ý5,Ž¡‘F¿ opt3‘)ÿè=‘?ý6,Ž¡‘F¿ opt4‘)ÿè=‘?ý7,Ž¡‘F¿ opt5‘)ÿè=‘?ý8,Ž¡‘F¿ opt6‘)ÿè=‘?ý9,Ž¡‘F¿ opt7‘)ÿè=‘?ý10,Ž¡‘F¿ opt8‘)ÿè=‘?ý11,Ž¡‘F¿ opt9‘)ÿè=‘?ý12,Ž¡‘F¿ backup‘î=‘?ý13,Ž¡‘F¿ break_space–?ý=“14,Ž¡‘F¿ force‘$¿ë=‘?ý15,Ž¡‘F¿ big_force‘¿÷=‘?ý16,Ž¡‘F¿ no_indent‘¿÷=‘?ý17,Ž¡‘F¿ cancel‘î=‘?ý18Ž¡‘1¿¬};Ž¡¦‘'¿¬²As–ÀÔthe“format“commands“are“declared“as“an“enš¸ãumeration“t˜ypGe,‘Þˆthey“are“represen˜tedŽ¡‘'¿¬bš¸ãy–~Óa“n˜um˜bGer“at“run“time.‘î@T‘ÿ*ªo“nev˜ertheless“ha˜v˜e“access“to“the“actual“Ìname“²of“aŽ¡‘'¿¬format–‚Õcommand“there“is“an“arraš¸ãy“of“strings“presen˜t“from“whic˜h“the“name“of“aŽ¡‘'¿¬format–UUcommand“can“bGe“w¸ãon.Ž¡‘6¿¬So–UUsuppGose“¹fc“²is“a“format“command,“thenޤ‘@¿®¹Format_command_str[fc]Ž¡‘'¿¬²is–UUthe“name“of“¹fc“²as“a“string“(¹char*²).ަ‘ \¼4bŽ‘'¿¬¸hÌDe nition–“çof“format“c‘ÿ}'ommands“¼4a¸iŽ’Ä—§²+Ž’Ì^ŸŽŽ¤ ‘1¿¬¹extern–?ýchar“*Format_command_str[];Ž¡ŽŸ’Ùìx²4ŽŽŒ‹! É ýC Ÿ ýÔ*«ŸÆUUŸçæd‘.ðí¹Output(ostream&)Ž’ß0–²constructor,‘Çásends–¤„all“output“to“this“ob-ŽŸ ’ß0–ject–UUto“the“giv¸ãen“¹ostreamŽŽŽŽŸ‘.ðí~Output()Ž’ß0–²destructorŽŽŽŽ¤ ‘.ðí¹do_output(char*)Ž’¾0¢voidŽ’ß0–²output–UUa“stringŽŽŽŽ¡‘.ðí¹do_output(Format_command)Ž’¾0¢voidŽ’ß0–²output–UUa“format“commandŽŽŽŽŽŽŽŸ-qÇ‘t>@T‘ÿ*ªable–UU2:‘qÇMem¸ãbGer“functions“of“the“¹Output“²class.ŽŽŽŸÖ‘'¿¬É3Ž‘@ wTŒÌyp•s3esetter‘ffDep“endenceŽ©ç‘'¿¬²As–|Amenš¸ãtioned“abGo˜v˜e,‘…üthe“in˜terpretation“of“format“commands“b˜y“the“output“deviceޤ ‘'¿¬(the––¹t¸ãypšGesetter)“dep˜ends“on“the“capabilities“of“this“`mac¸ãhine'.‘2>F‘ÿ*ªor“example,‘¼Øa“simpleŽ¡‘'¿¬matrix-dot–6¬line“prinš¸ãter“will“ha˜v˜e“problems“doing“a“Ìb‘ÿ}'ackupŽ‘#or“determining“the“placeŽ¡‘'¿¬of–¼a“line“break“bš¸ãy“itself,‘Ûwhereas“a“sophisticated“formatting“system“lik˜e“T‘þU>Ÿ'EŽ‘ãxX“will“bGeŽ¡‘'¿¬able–UUto“do“all“this“and“ev¸ãen“more.Ž¡‘6¿¬It–äRis“clear,‘úìthat“the“t¸ãypšGesetter“dep˜endence“starts“on“a“lev¸ãel“b˜elo¸ãw“the“formattingŽ¡‘'¿¬commands.‘4¾Indeed,‘ÂÙformatting–ž:commands“ha•¸ãv“e–ž:bšGeen“in¸ãtro˜duced“sp˜eci cally“to“ha•¸ãv“eŽ¡‘'¿¬an–/(abstraction“of“formatting“requiremenš¸ãts.‘ÿ?So“the“t˜ypšGesetter“dep˜endence“can“b˜eŽ¡‘'¿¬encapsulated–UUwithin“the“¹Output“²class“presen¸ãted“here.Ž¡‘6¿¬Hoš¸ãw–€Ýis“this“done?‘*õIn“general,‘«[ob‘Ž8jects“of“the“¹Output“²class“are“ lters“that“in˜terpretŽ¡‘'¿¬a–°‹stream“of“attributes“and“put“them“inš¸ãto“a“form“that“the“t˜ypGesetter“can“understand.Ž¡‘'¿¬W‘ÿ*ªe–|Icannot“hardcoGde“this“inš¸ãterpretation“in˜to“the“class,‘†as“this“w˜ould“inhibit“a“userŽ¡‘'¿¬from–âÇusing“sevš¸ãeral“prett˜yprin˜ters“with“di eren˜t“targets“in“a“single“program.‘HereŽ¡‘'¿¬ob‘Ž8ject–UUorienš¸ãted“approac˜hes“come“in“handy‘ÿ*ª.Ž¡‘6¿¬W‘ÿ*ªe–<~will“think“of“t¸ãypšGesetter“dep˜enden¸ãt“output“ob‘Ž8jects“as“sp˜ecializations“of“anŽ¡‘'¿¬`abstract'–Ë.output.‘ÓSThis“maps“to“the“idea“of“ha¸ãving“an“abstract“base“class“¹OutputŽ¡‘'¿¬²and–_Gha¸ãving“one“subšGclass“p˜er“t¸ãyp˜esetter“that“wš¸ãe“w˜an˜t“as“target.‘The“spGecializedŽ¡‘'¿¬subGclasses›(ha•¸ãv“e˜all˜t“yp•Gesetter˜dep“endencies˜built˜in˜to˜them˜and˜the˜abstract˜baseŽ¡‘'¿¬class–UUdoGes“nothing“else“as“dynamic“dispatc¸ãh.Ž¡‘6¿¬This–‹moGdule“will“presenš¸ãt“the“abstract“base“class“de nition“and“will“sho˜w“b˜yŽ¡‘'¿¬example–2ho¸ãw“to“build“a“spGecialized“¹Output“²class.‘f0The“example“has“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“as“targetŽ¡‘'¿¬t¸ãypGesetter.ŽŸ!ã‘'¿¬É4Ž‘@ wUsing–ffthe“Output“Class“(OvŒÌerview)ަ’ #ÌOutputs–“çoutput“attributes.ŽŸÌr‘'¿¬²Here–³2noš¸ãw“is“an“o˜v˜erview“of“ho˜w“to“use“¹Outputs².‘‹_Y‘ÿ*ªou“need“at“least“one“output“toŽ¡‘'¿¬output–¾Tan“attribute.‘?rOutputs“ha•¸ãv“e–¾Tthe“in¸ãterpretation“of“the“format“commands“builtŽ¡‘'¿¬in–Óto“them.‘¶AHo•¸ãw“ev“er,‘G2as–Óthis“is“t¸ãypšGesetter“dep˜enden•¸ãt.‘¶Ay“ou–Ówill“need“to“c¸ãho˜ose“aŽ¡‘'¿¬sp•Geci c›UUsub“class˜of˜the˜¹Output˜²class.Ž¡‘6¿¬T‘ÿ*ªable–€2“lists“the“functions“yš¸ãou“can“use“on“an“output.‘ñßSo,‘Š´if“y˜ou“w˜an˜t“to“createŽ¡‘'¿¬an–woutput“called“¹outp“²that“is“connected“to“the“output“stream“¹os²,‘~then“y¸ãou“shouldŽ¡‘'¿¬saš¸ãy–UUsomething“lik˜e“this:Ž©ÖÁ‘@¿®¹Output‘?ýoutp(os);ŽŸÖ‘'¿¬²The›Ío•¸ãv“erloaded˜¹do_output˜²mem“b•Ger˜function˜do“es˜automatic˜in¸ãterpretation˜of˜theŽ¡‘'¿¬format–UUcommands.‘qÇSo,“if“¹o“²is“an“output“the“commandަ‘@¿®¹o.do_output(force);ŽŸÖ‘'¿¬²will–>ÆproGduce“an“in¸ãterpretation“of“a“Ìfor–ÿ}'c“eŽ‘ÐX²format“command“on“the“output“streamŽ¡‘'¿¬connected–UUto“the“output.‘qÇThe“sequenceŽŽŸ’Ùìx5ŽŽŒ‹(à É ýC Ÿ ý°*«ŸØUUŸùæd‘S°Ø¹debug_on()Ž’™p·voidŽ’ºp«²start–UUmaking“format“commands“visibleŽŽŽŽŸ ‘S°Ø¹debug_off()Ž’™p·voidŽ’ºp«²end–UUdebug“moGdeŽŽŽŽŽŽŽŸqÇ‘TÚ­T‘ÿ*ªable–UU3:‘qÇSpšGecial“debug“mem¸ãb˜er“functions“of“the“¹Output“²class.ŽŽŽŸ‘@¿®¹o.do_output("some‘?ýtext");ŽŸ‘'¿¬²will–UUsimply“pass“this“string“on“to“the“same“output“stream.ŽŸþ6‘'¿¬ó%ÂÖN  cmbx12ÐDebuggingŽŸuT‘'¿¬²T‘ÿ*ªable–þÅ3“shoš¸ãws“t˜w˜o“spGecial“debug“mem˜bšGer“functions“that“can“b˜e“called“on“an“outputޤ ‘'¿¬ob›Ž8ject.‘EThey–Ьmak¸ãe“the“format“commands“passed“to“the“output“ob˜ject“visible“bGeforeŽ¡‘'¿¬they–UUare“in¸ãterpreted:Ž¡‘6¿¬If–N€y¸ãou“call“¹debug_on“²on“an“output“ob‘Ž8ject“it“will“output“the“name“of“the“formatŽ¡‘'¿¬command–cßas“string“to“the“connected“output“stream.‘dThis“name“is“encapsulatedŽ¡‘'¿¬in–¥¼angled“brac•¸ãk“ets–¥¼but“this“can“bGe“cš¸ãhanged“(see“page“7).‘büThe“¹debug_off“²mem˜bGerŽ¡‘'¿¬function–UUturns“all“this“o “again.ŽŸ!Ä‘'¿¬É5Ž‘@ wThe–ffInŒÌterface“to“the“Output“Class“(Details)ŽŸç‘'¿¬²Here–µÉat“last“is“the“ nal“reference“of“the“abstract“base“class.‘“"The“priv‘ÿqÇate“and“pro-Ž¡‘'¿¬tected–UUmemš¸ãbGers“are“only“in˜teresting“for“the“implemen˜tation.ŽŸ‘ ÑD¼6Ž‘'¿¬¸hÌDe nition–“çof“the“¹Output“Ìclass“¼6¸iŽ’ºgCŽ¡‘1¿¬¹class–?ýOutput“{Ž¡‘1¿¬public:Ž¡‘[¿”Output(ostream&‘?ýostr);Ž¡‘[¿”virtual‘?ý~Output();Ž¡‘[¿”void‘?ýdo_output(char*);Ž¡‘[¿”void‘?ýdo_output(Format_command);Ž¡¡‘[¿”¸hÌDebug–“çmemb‘ÿ}'er“functions“of“the“¹Output“Ìclass“¼7b¸iŽŽ¡‘1¿¬¹protected:Ž¡‘[¿”¸hÌPr–ÿ}'ote“cte“d›“çmemb“ers˜of˜the˜¹Output˜Ìclass˜Ï??¸iŽŽ¡‘1¿¬¹private:Ž¡‘[¿”¸hÌPrivate–“çmemb‘ÿ}'ers“of“the“¹Output“Ìclass“Ï??¸iŽŽ¡‘1¿¬¹};Ž¡ŽŸ’Ùìx²6ŽŽŒ‹7‰ É ýC Ÿ ý„‘6¿¬²It–r”is“impGortanš¸ãt“to“note“here“that“the“output“is“bu ered“with“one“elemen˜t“ofޤ ‘'¿¬lošGok‘ÿqÇahead.‘RAThis–öÃis“necessary“b˜ecause“of“the“in¸ãterpretation“p˜erformed“on“the“formatŽ¡‘'¿¬commands.‘d_Y‘ÿ*ªou–ûˆcan“only“bšGe“sure“that“a“format“command“has“b˜een“output“un¸ãtilŽ¡‘'¿¬y•¸ãou›E=ha“v“e˜destro“y“ed˜the˜output˜ob‘Ž8ject˜with˜the˜destructor˜or˜un“til˜y“ou˜ha“v“e˜outputŽ¡‘'¿¬a‘UUstring.Ž¡‘'¿¬Y‘ÿ*ªou–ˆ³can“switcš¸ãh“on“a“debug“moGde“as“y˜ou“use“an“output“if“y˜ou“call“the“mem˜bGerŽ¡‘'¿¬function–©¹debug_on².‘ ÄIf“an“output“is“in“debug“moGde,‘>>it“not“only“in¸ãterprets“formatŽ¡‘'¿¬commands,‘N but–L7also“prin¸ãts“out“the“names“of“the“format“commands“to“the“¹ostreamŽ¡‘'¿¬Ìb–ÿ}'efor“e–v'²they“are“inš¸ãterpreted.‘Ô>(This“is“impGortan˜t“bGecause“some“format“commandsŽ¡‘'¿¬nevš¸ãer–´Àare“actually“output,‘ÔÞlik˜e“¹cancel².)‘<@These“names“are“surrounded“b˜y“t˜w˜o“stringsŽ¡‘'¿¬¹bs–h²(for“\bGeginning“string")“and“¹es“²(for“\ending“string")“that“y¸ãou“can“pass“on“toŽ¡‘'¿¬¹debug_on–(²as“argumenš¸ãts.‘uASo“if“y˜ou“are“using“T‘þU>Ÿ'EŽ‘ãxX“y˜ou“could“switc˜h“on“the“debugŽ¡‘'¿¬option‘UUwithޤ‘@¿®¹o.debug_on("%‘?ý","\n");Ž¡‘'¿¬²to–UUmakš¸ãe“these“names“in˜visible“for“T‘þU>Ÿ'EŽ‘ãxX.ޤ ‘6¿¬Note–I·that“the“con•¸ãten“ts–I·of“¹bs“²and“¹es“²are“copied.‘“Y‘ÿ*ªou“can“re-use“the“string“pGoin¸ãtersŽ¡‘'¿¬later–¤if“yš¸ãou“wish.‘¹µThe“maxim˜um“length“of“the“bGeginning“and“ending“delimiters“isŽ¡‘'¿¬set–ú™to“¹max_debug_del_size².‘SˆIf“y¸ãou“pass“on“longer“strings“to“¹debug_on“²they“will“bGeŽ¡‘'¿¬cut–UUo “after“the“givš¸ãen“n˜um˜bGer“of“c˜haracters.Ž©‘ ‘@¼7aŽ‘'¿¬¸hÌMacr›ÿ}'o–“çde nitions“in“the“sp˜e˜ci c˜ation“¼7a¸iŽ’ÜÀÕŽ¡‘1¿¬¹#define‘?ýmax_debug_del_size‘IÖ10ަ‘6¿¬²The–¯`default“setting“for“the“¹debug_on“²mem¸ãbGer“function“is“with“¹"["“²and“¹"]"“²asŽ¡‘'¿¬bšGeginning–õand“ending“strings.‘\ýY‘ÿ*ªou“can“switc¸ãh“o “the“debug“mo˜de“with“¹debug_off².ަ‘ \¼7bŽ‘'¿¬¸hÌDebug–“çmemb‘ÿ}'er“functions“of“the“¹Output“Ìclass“¼7b¸iŽ’ÿ$OŽ¡‘1¿¬¹void–?ýdebug_on(char“*bs“=“"[",“char“*es“=“"]"“);“/*“turn“on“debug“mode“*/Ž¡‘1¿¬void–?ýdebug_off();“/*“get“back“to“normal“mode“again“*/ŽŸ&Ä‘'¿¬É6Ž‘@ wAn–ffOutput“for“LaT‘þ¦feXŽŸç‘'¿¬²This–­+section“will“givš¸ãe“an“example“on“ho˜w“to“build“y˜our“o˜wn“t˜ypšGesetter“dep˜enden¸ãtŽ¡‘'¿¬output–f^class.›¤ãHere“I‘fwill“presen¸ãt“a“spGecialized“output“for“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX.˜T‘ÿ*ªo“build“y¸ãourŽ¡‘'¿¬o¸ãwn–"SsubšGclass“for“a“sp˜ecialized“target“lo˜ok“inš¸ãto“the“user“man˜ual“or“confer“the“ leŽ¡‘'¿¬¹blankoutput.nw².Ž¡‘'¿¬The–8ã rst“thing“yš¸ãou“ha˜v˜e“to“do“is“to“think“of“a“go•Go“d–8ãname.‘÷I`ll“tak˜e“¹Latex_cweb_output²,Ž¡‘'¿¬bGecause–0ÿthe“target“is“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“and“the“in¸ãterpretation“of“format“commands“is“basedŽ¡‘'¿¬upGon–UUthe“macros“of“the“¹CWEB“²system.Ž¡‘6¿¬Noš¸ãw–UUthat“w˜e“ha˜v˜e“a“name,“w˜e“can“presen˜t“the“class“declaration.ަ‘ $¼7cŽ‘'¿¬¸hÌDe nition–“çof“the“¹Output“Ìclass“¼6¸iŽ’ºgC²+Ž’Â.a¸ŽŽ¡‘1¿¬¹class–?ýLatex_cweb_output“:“public“Output“{Ž¡‘1¿¬public:Ž¡‘F¿ Latex_cweb_output(ostream&–?ýostr)“:“Output(ostr)“{};Ž¡‘F¿ ~Latex_cweb_output()–?ý{“flush_output();“};Ž¡‘1¿¬private:Ž¡‘F¿ void‘?ýflush_output();Ž¡‘1¿¬};Ž¡ŽŸ’Ùìx²7ŽŽŒ‹> É ýC Ÿ ý„‘'¿¬²Y‘ÿ*ªes,‘¬git`s–gÊas“simple“as“that.‘©%ExpGerienced“readers“will“ha•¸ãv“e–gÊnoticed“that“only“theޤ ‘'¿¬¹flush_output–¬Á²routine“w¸ãas“a“virtual“function“and“indeed,‘œit“is“this“single“functionŽ¡‘'¿¬that–E%encapsulates“the“whole“translation.‘A6So“the“next“thing“yš¸ãou“ha˜v˜e“to“do“is“toŽ¡‘'¿¬de ne–Ïothe“function“¹flush_output“²in“an“implemenation“ le.‘E%As“the“only“things“thatŽ¡‘'¿¬cš¸ãhange–¨;in“di eren˜t“implemen˜tations“are“the“translations“of“the“format“commands,Ž¡‘'¿¬there–s˜is“a“spGecial“ le“in“whicš¸ãh“y˜ou“only“ha˜v˜e“to“replace“preproGcessor“macro“stringsŽ¡‘'¿¬to–UUdo“this.Ž¡‘'¿¬T›ÿ*ªo–…øuse“the“LaT˜eX‘…©output,‘Ò yš¸ãou`ll“ha˜v˜e“to“build“a“prett˜yprin˜ter“with“pretzel“andŽ¡‘'¿¬spšGecify–`¹Latex_cweb_output“²as“output“class“to“use.‘ The“prett•¸ãyprin“ted–`co˜de“will“ha•¸ãv“eŽ¡‘'¿¬spGecial–Z macros“inserted“in¸ãto“the“output“that“are“de ned“in“¹pretzel-latex.sty².Ž¡‘'¿¬No•¸ãw›‹y“ou˜can˜use˜a˜new˜en“vironmen“t˜called˜¹ppcode².‘jIn“bGet“w“een˜this˜en“vironmen“tŽ¡‘'¿¬the–UUcošGde“will“b˜e“formatted“nicely‘ÿ*ª.ŽŸ!Ä‘'¿¬ÉIdenŒÌti er‘ffIndexŽŽŸ’Ùìx²8ŽŽŒøK߃’À;èÉ‘E ó%ÂÖN  cmbx12ó$2Ç@Écmbx8ó!ý': cmti10ó Œ-ø cmcsc10óò"V cmbx10óÂÖN ff cmbx12óߤN cmtt9óŒ-ø cmcsc10ót ‰: cmbx9óo´‹Ç cmr9ó¹Aa¨cmr6ó|{Ycmr8óX«Q cmr12óDÓítG®G®cmr17óßê cmmi10óKñ`y cmr10óÙ“ Rcmr7ùP˜ßßßßßßßpretzel-2.0n-2/output/test.output.correct0000644000000000000000000000074706121530457017327 0ustar rootrootStarting to test the outputs... Doing first round of testing: if (x<0) then\pretzelindent{}\pretzelforce{}begin abs:=-1 end;\pretzeloutdent{}\pretzelforce{} Doing second round of testing: if (x<0) then[indent]\pretzelindent{}[force]\pretzelforce{}begin abs:=-1 end;[outdent]\pretzeloutdent{}[force]\pretzelforce{} Doing third round of testing: if (x<0) then/*indent*/\pretzelindent{}/*force*/\pretzelforce{}begin abs:=-1 end;/*outdent*/\pretzeloutdent{}/*force*/\pretzelforce{} Done. pretzel-2.0n-2/WHATSNEW0000644000000000000000000000004106360664051013237 0ustar rootrootSee the file `diary' Sorry. FG pretzel-2.0n-2/man/0000755000000000000000000000000010765025503012631 5ustar rootrootpretzel-2.0n-2/man/pretzel-it.10000644000000000000000000001325306537760763015036 0ustar rootroot.\" $Id: pretzel-it.1,v 2.3 1998/04/25 08:10:58 gaertner Exp $ .\" manpage for pretzel-it! .TH pretzel-it 1 "June 11, 1998" .ds ]W Release 2.0k: June 1998 .SH NAME pretzel-it \- use Pretzel to build a prettyprinter .SH SYNOPSIS pretzel-it [-iqvdnh] language ppname .SH DESCRIPTION Pretzel-it is a shell script that uses .B pretzel(1) to build a simple prettyprinter executable. It minimizes building a Pretzel prettyprinter to just one shell command. See .B pretzel(1) for a general overview and a description of the input files. You have to provide the same two input files to pretzel-it as to pretzel. These two files are called the .B formatted token file (suffix .BR .ft ) and the .B formatted grammar file (suffix .BR .fg ). Both files need to have the same prefix .BR language . From this input, pretzel-it generates an executable prettyprinter called .BR ppname . .SS Example Say, you have written two files .B foo.ft and .B foo.fg that contain the prettyprinting information for your favourite programming language .IR foo . To get an executable prettyprinter .B foopp for it, simply type: .RS .B pretzel-it foo foopp .RE .SH "OPTIONS" Pretzel-it has the following options: .RS .TP .B -i Don't remove intermediate products of pretzeling. .TP .B -q Run quietly. .TP .B -v Verbose mode, print shell commands before invoking (for debugging). .TP .B -d Turn prettyprinter debugging features on by default; also produce a detailed diagnosis file (suffix .BR .output ) that contains a detailed analysis of the grammar and possible problems with it (to ease debugging the prettyprinting grammar). .TP .B -h Print full usage message. .TP .B -n Noweb mode. See section .B Interfacing with noweb(1) below. .RE .SH "THE GENERATED PRETTYPRINTER" The generated executable will be a program that reads source code from the standard input and will write prettyprinted code to the standard output. The prettyprinted code can be typeset using .B latex together with the .B pretzel-latex document style. .SS Example Say, you have built .B foopp already and have a scrap of source code in a file .BR bar.foo . Type .RS .B foopp bar.tex .RE and the prettyprinter will prettyprint the code and write LaTeX code to .BR bar.tex . To use this code in your documents, simple include the .B pretzel-latex document style and include the file inside the new .B ppcode LaTeX environment. Here's a minimal LaTeX file to look at the prettyprinted code: .RS .PD 0 .B \edocumenstyle[pretzel-latex]{article} .PP .B \ebegin{document} .PP .B \ebegin{ppcode} .PP .B \einput{foo.tex} .PP .B \eend{ppcode} .PP .B \eend{document} .RE .PD .SH "INTERFACING WITH NOWEB" Using the .BR -n option will produce a prettyprinting filter .BR ppname compatible to Norman Ramsey's .BR noweb(1) literate programming system. The filter can be inserted into the noweb pipeline using noweave's .BR -filter option. For example, you can build a noweb prettyprinting filter for Pascal by issuing .RS .B pretzel-it -n pascal prettypascal .RE inside the .B languages/pascal directory, you'll get a prettyprinting filter .B prettypascal . This filter then can be used within .B noweave(1) by saying: .RS .B noweave -filter prettypascal foo.nw > foo.tex .RE This will prettyprint all code chunks using the Pascal prettyprinter. You will need to include the .B pretzel-noweb.sty LaTeX document style after including the .B noweb.sty ( see .B nowebstyle(1) ) to get the output typeset correctly by LaTeX. You can get debugging output from the prettyprinting filter by setting the environment variable .B PRETZEL_NOWEB_DEBUG to a non-null value, e.g. in the .B bash(1) shell by saying: .RS .B export PRETZEL_NOWEB_DEBUG=on .RE Debug output stops only when the value is explicitly unset (in .B bash(1) this is the .B unset builtin command. The noweb option at present works only for LaTeX as target typesetter. If the prettyprinter experiences problems when prettyprinting a certain code chunk, it automatically switches to standard verbatim output of noweb. Through the inclusion of code within rules of the formatted grammar file it is possible to automate indexing. For more information see chapters 3 and 4 of the Pretzelbook, contained in the Pretzel distribution. .SH CAVEATS The pretzel-it shell script can only be run if the environment variables .B PRETZEL_LIBDIR and .B PRETZEL_INCLUDE are set to the Pretzel library directory (/usr/lib/pretzel on Debian systems) and the Pretzel include directory (/usr/include/pretzel on Debian systems). During execution, pretzel-it might issue warnings that are due to the programs it invokes (pretzel-it invokes .BR pretzel(1) ", " flex(1) ", " bison(1) and the GNU C++ compiler). The .B -n (noweb) option works only for LaTeX as target typesetter and is still very much experimental. .SH FILES .PD 0 .TP 30 .B /usr/lib/pretzel/libpretzel.a pretzel runtime library. .TP .B /usr/include/pretzel directory for runtime library include files. .TP .B /usr/include/pretzel/pscan.h .TP .B /usr/include/pretzel/pparse.h template headers for the generated functions. .TP .B /usr/lib/texmf/tex/latex/pretzel/pretzel-latex.sty LaTeX style to typeset Pretzel output. .TP .B /usr/lib/pretzel/plainpp.o simple main program linked to the prettyprinter object generated by Pretzel. .TP .B /usr/lib/pretzel/plaindpp.o simple main program linked to the prettyprinter object generated by Pretzel with debug features. .B /usr/lib/pretzel/nowebpretzelpp.o main program the interfaces the Preztel prettyprinter with noweb. .PD .SH "SEE ALSO" .PD 0 pretzel(1), noweb(1) .PP .I "The Pretzelbook" by Felix Gaertner, included in the Pretzel distribution. .PP The Pretzel homepage on the WWW at .B http://www.iti.informatik.tu-darmstadt.de/~gaertner/pretzel .PD .SH AUTHOR Felix Gaertner, email: fcg@acm.org pretzel-2.0n-2/man/pretzel.1.ps0000644000000000000000000010732306502165325015030 0ustar rootroot%!PS-Adobe-3.0 %%Creator: groff version 1.10 %%CreationDate: Fri Mar 13 09:14:13 1998 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Times-Italic %%DocumentSuppliedResources: procset grops 1.10 0 %%Pages: 7 %%PageOrder: Ascend %%Orientation: Portrait %%EndComments %%BeginProlog %%BeginResource: procset grops 1.10 0 /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /MANUAL{ statusdict begin/manualfeed true store end }bind def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 72 RES div dup scale LS{ 90 rotate }{ 0 PL translate }ifelse 1 -1 scale }bind def /EP{ level0 restore showpage }bind def /DA{ newpath arcn stroke }bind def /SN{ transform .25 sub exch .25 sub exch round .25 add exch round .25 add exch itransform }bind def /DL{ SN moveto SN lineto stroke }bind def /DC{ newpath 0 360 arc closepath }bind def /TM matrix def /DE{ TM currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath TM setmatrix }bind def /RC/rcurveto load def /RL/rlineto load def /ST/stroke load def /MT/moveto load def /CL/closepath load def /FL{ currentgray exch setgray fill setgray }bind def /BL/fill load def /LW/setlinewidth load def /RE{ findfont dup maxlength 1 index/FontName known not{1 add}if dict begin { 1 index/FID ne{def}{pop pop}ifelse }forall /Encoding exch def dup/FontName exch def currentdict end definefont pop }bind def /DEFS 0 def /EBEGIN{ moveto DEFS begin }bind def /EEND/end load def /CNT 0 def /level1 0 def /PBEGIN{ /level1 save def translate div 3 1 roll div exch scale neg exch neg exch translate 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit []0 setdash /setstrokeadjust where{ pop false setstrokeadjust }if /setoverprint where{ pop false setoverprint }if newpath /CNT countdictstack def userdict begin /showpage{}def }bind def /PEND{ clear countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Bold %%IncludeResource: font Times-Italic grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron /scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent /ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen /period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon /semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O /P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex /underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y /z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft /guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl /endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut /dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash /quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen /brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft /logicalnot/minus/registered/macron/degree/plusminus/twosuperior /threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior /ordmasculine/guilsinglright/onequarter/onehalf/threequarters /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash /ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def /Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE /Times-Roman@0 ENC0/Times-Roman RE %%EndProlog %%Page: 1 1 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R/F1 9 /Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0(pretzel \255 the uni)108 96 Q -.15(ve)-.25 G(rsal prettyprinter generator).15 E F1(SYNOPSIS)72 112.8 Q F0(pretzel [-qtgdh] [-o out\214le] \214lepre\214x)108 124.8 Q (pretzel [-qtgdh] [-o out\214le] \214le1 \214le2)108 148.8 Q F1 (DESCRIPTION)72 165.6 Q F0 .93(Pretzel is a program that generates a pr\ ettyprinter module from a formal description of the w)108 177.6 R .93 (ay a certain)-.1 F .392(language should be prettyprinted.)108 189.6 R (A)5.392 E/F2 10/Times-Bold@0 SF(pr)2.892 E(ettyprinter)-.18 E F0 .393 (is a function or program that rearranges source code to)2.893 F 1.596 (enhance its readability)108 201.6 R 6.596(.P)-.65 G 1.596 (rettyprinters generated by pretzel output LaT)-6.596 F 1.595 (eX source code that can be used)-.7 F(within your o)108 213.6 Q (wn documents.)-.25 E(NB that pretzel produces)5 E F2(modules)2.5 E F0 2.5(,n)C(ot programs!)-2.5 E -1.1(Yo)108 237.6 S 4.311(uh)1.1 G -2.25 -.2(av e)-4.311 H 1.811(to pro)4.511 F 1.811(vide tw)-.15 F 4.311(oi)-.1 G 1.811(nput \214les to pretzel that specify the w)-4.311 F 1.811(ay gi) -.1 F -.15(ve)-.25 G 4.311(ns).15 G 1.811(ource code should be pret-) -4.311 F .607(typrinted. These tw)108 249.6 R 3.107<6f8c>-.1 G .607 (les are called the)-3.107 F F2 -.25(fo)3.107 G .607(rmatted tok).25 F .607(en \214le)-.1 F F0(\(suf)3.107 E<8c78>-.25 E F2(.ft)3.107 E F0 3.107(\)a)C .607(nd the)-3.107 F F2 -.25(fo)3.107 G .606 (rmatted grammar \214le).25 F F0(\(suf)108 261.6 Q<8c78>-.25 E F2(.fg) 2.5 E F0(\).)A .177(From this input, pretzel generates tw)108 285.6 R 2.677(ot)-.1 G .177(hings: a v)-2.677 F(alid)-.25 E F2(\215ex\(1\))2.678 E F0 .178(\214le that forms the)2.678 F F2(pr)2.678 E .178 (ettyprinting scanner)-.18 F F0(and)2.678 E 3.605(av)108 297.6 S(alid) -3.855 E F2(bison\(1\))3.605 E F0 1.105 (input \214le that can be used to b)3.605 F 1.105(uild the)-.2 F F2(pr) 3.605 E 1.105(ettyprinting parser)-.18 F F0 1.105 (\(which is the actual pret-)3.605 F 3.097(typrinter\). There)108 309.6 R .597(is a shell script)3.097 F F2(pr)3.097 E(etzel-it)-.18 E F0 .597 (that f)3.097 F .597(aciliates using pretzel \(see)-.1 F F2(pr)3.098 E (etzel-it\(1\))-.18 E F0 3.098(\). This)B .598(man page)3.098 F .183 (is only meant as a quick reference to pretzel usage.)108 321.6 R .183 (Look into the main documentation of pretzel if you are)5.183 F(ne)108 333.6 Q 2.5(wt)-.25 G 2.5(oa)-2.5 G(ll this.)-2.5 E F2(In)87 350.4 Q -.1 (vo)-.4 G(king pr).1 E(etzel)-.18 E F0(In)108 362.4 Q -.2(vo)-.4 G .753 (king pretzel can tak).2 F 3.253(et)-.1 G .953 -.1(wo f)-3.253 H .753 (orms: Either in).1 F -.2(vo)-.4 G .953 -.1(ke i).2 H 3.254(ts).1 G .754 (pecifying only the common pre\214x of the tw)-3.254 F 3.254(oi)-.1 G (nput)-3.254 E .166(\214les, or specify both \214les seperately on the \ command line. If you specify both \214les, the formatted tok)108 374.4 R .165(en \214le)-.1 F(comes \214rst.)108 386.4 Q F2(Examples)87 403.2 Q F0(Say your input \214les are called)108 415.2 Q F2 -.25(fo)2.5 G(o.ft) .25 E F0(and)2.5 E F2 -.25(fo)2.5 G(o.fg).25 E F0 5(.T)C (hen you can say)-5 E F2(pr)144 432 Q(etzel f)-.18 E(oo)-.25 E F0(to in) 108 448.8 Q -.2(vo)-.4 G .2 -.1(ke p).2 H(retzel properly).1 E 2.5(.I) -.65 G 2.5(fy)-2.5 G(our \214les are called)-2.5 E F2 -.25(fo)2.5 G (o.ft).25 E F0(and)2.5 E F2(bar)2.5 E(.fg)-1 E F0(then you w)2.5 E (ould ha)-.1 E .3 -.15(ve t)-.2 H 2.5(os).15 G(ay)-2.5 E F2(pr)144 465.6 Q(etzel f)-.18 E(oo.ft bar)-.25 E(.fg)-1 E F0(to do the job)108 482.4 Q (.)-.4 E F1(OPTIONS)72 499.2 Q F0(Pretzel recognizes the follo)108 511.2 Q(wing options:)-.25 E F2(-q)144 528 Q F0(Run quietly)27.11 E(.)-.65 E F2(-t)144 544.8 Q F0(Process formatted tok)29.34 E(en \214le only)-.1 E (.)-.65 E F2(-g)144 561.6 Q F0 (Process formatted grammar \214le only \(options)27.67 E F2(-t)2.5 E F0 (and)2.5 E F2(-g)2.5 E F0(are mutually e)2.5 E(xclusi)-.15 E -.15(ve) -.25 G(\).).15 E F2(-d)144 578.4 Q F0(Print deb)27.11 E (ug information to the screen.)-.2 E F2(-h)144 595.2 Q F0 (Print full usage message.)27.11 E F2(-o name)144 612 Q F0(Use)180 624 Q F2(name)2.5 E F0(as pre\214x of the generated output \214les.)2.5 E F1 (THE INPUT FILES)72 640.8 Q F0 .052 (This section summarizes the format of the input \214les and the)108 652.8 R F2 -.25(fo)2.553 G .053(rmat command primiti).25 F -.1(ve)-.1 G (s).1 E F0 .053(that pretzel sup-)2.553 F(ports.)108 664.8 Q F2(The f)87 681.6 Q(ormatted tok)-.25 E(en \214le)-.1 E F0 .708(The formatted tok) 108 693.6 R .708(en \214le contains a list of tok)-.1 F .708 (en de\214nitions with their corresponding "prettyprinted" form.)-.1 F (The prettyprinted form of a tok)108 705.6 Q(en will be called an)-.1 E F2(attrib)2.5 E(ute)-.2 E F0(or a)2.5 E F2(translation)2.5 E F0(.)A (The general outline of the formatted tok)108 729.6 Q(en \214le is)-.1 E (March 13, 1998)274.2 768 Q(1)197.2 E EP %%Page: 2 2 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R/F1 10 /Times-Italic@0 SF(declar)144 84 Q(ations)-.15 E F0(%%)144 108 Q F1(tok) 144 132 Q(en de\214nitions)-.1 E F0(Normally)108 156 Q 3.459(,t)-.65 G (he)-3.459 E F1(declar)3.459 E(ations)-.15 E F0 .959(part is empty)3.459 F 3.459(.Y)-.65 G .96 (ou can put a general description of the \214le here \(as a C com-) -4.559 F(ment\) and rede\214nitions of the def)108 168 Q(ault interf)-.1 E(ace go here as well.)-.1 E(The)108 192 Q F1(tok)2.5 E (en de\214nitions)-.1 E F0(section of the formatted tok)2.5 E (en \214le contains a series of tok)-.1 E(en de\214nitions of the form:) -.1 E F1(pattern tok)144 208.8 Q(en attrib)-.1 E(ute)-.2 E F0(The)108 232.8 Q F1(pattern)3.804 E F0 1.304(must be a v)3.804 F 1.304(alid re) -.25 F 1.304(gular e)-.15 F 1.304(xpression \(in terms of)-.15 F/F2 10 /Times-Bold@0 SF(\215ex\(1\))3.803 E F0 3.803(\)a)C 1.303 (nd must be unindented. The)-3.803 F F1(tok)3.803 E(en)-.1 E F0 1.118 (speci\214es the symbolic name of the tok)108 244.8 R 1.118 (en for the pattern and be)-.1 F 1.118 (gins at the \214rst non-whitespace character)-.15 F .418 (after the pattern. The tok)108 256.8 R .418(en name must be a le)-.1 F -.05(ga)-.15 G 2.918(ln).05 G .417(ame for an identi\214er in P)-2.918 F .417(ascal notation and)-.15 F F2 .417(must be all)2.917 F (in upper case.)108 268.8 Q F0(\(Underlines are allo)5 E(wed b)-.25 E (ut not at the be)-.2 E(ginning of a w)-.15 E(ord.\))-.1 E(The)108 292.8 Q F1(attrib)4.138 E(ute)-.2 E F0 1.638(for this tok)4.138 F 1.638 (en, that is it')-.1 F 4.138(sp)-.55 G 1.638 (rettyprinted form, consists of all te)-4.138 F 1.639(xt between the tw) -.15 F 4.139(oc)-.1 G(urling)-4.139 E(brack)108 304.8 Q(ets)-.1 E F2({) 2.984 E F0(and)2.984 E F2(})2.984 E F0 5.484(.A)C(ttrib)-5.484 E .484(u\ tes can be either simple strings \(surrounded by double quotes\), forma\ t commands)-.2 F .394(\(see belo)108 316.8 R .394(w\), your o)-.25 F .395(wn C++ code \(enclosed in angled brack)-.25 F(ets)-.1 E F2([)2.895 E F0(and)2.895 E F2(])2.895 E F0 2.895(,s)C .395(ee belo)-2.895 F .395 (w\) or a combination of both)-.25 F .206 (joined together by an optional)108 328.8 R F2(+)2.706 E F0 .205 (sign. Attrib)2.705 F .205(ute de\214nitions can co)-.2 F -.15(ve)-.15 G 2.705(rs).15 G -2.15 -.25(ev e)-2.705 H .205(ral lines and the starting) .25 F F2({)2.705 E F0(needn')2.705 E(t)-.18 E .34 (stand on the same line as the tok)108 340.8 R .34(en de\214nition; ho) -.1 F(we)-.25 E -.15(ve)-.25 G 2.84(rs).15 G .34 (ubsequent lines must be indented with at least one)-2.84 F (blank or one tab)108 352.8 Q(.)-.4 E .565 (If you de\214ne strings as part of an attrib)108 376.8 R .565 (ute de\214nition, you ha)-.2 F .865 -.15(ve t)-.2 H 3.065(os).15 G .564 (pecify them in a C kind of f)-3.065 F .564(ashion, i.e.)-.1 F 1.065 (you can insert ne)108 388.8 R 1.065(wlines and tabs with)-.25 F F2(\\n) 3.566 E F0(and)3.566 E F2(\\t)3.566 E F0 6.066(.B)C 1.066(ut if you w) -6.066 F 1.066(ant to insert a backslash into a string, you)-.1 F (mustn')108 400.8 Q 3.417(tf)-.18 G(or)-3.417 E .916(get to put tw)-.18 F 3.416(ob)-.1 G(ackslashes)-3.416 E F2(\\\\)3.416 E F0 .916 (into the input \214le. This is especially note)3.416 F -.1(wo)-.25 G (rth).1 E 3.416(yi)-.05 G 3.416(fy)-3.416 G .916(ou are using)-3.416 F -.7(Te)108 412.8 S 2.5(Xa).7 G 2.5(st)-2.5 G(ypesetter)-2.5 E(.)-.55 E .225(If the de\214nition of the attrib)108 436.8 R .225 (ute is omitted pretzel creates an attrib)-.2 F .226 (ute for this pattern by def)-.2 F .226(ault. The def)-.1 F(ault)-.1 E (attrib)108 448.8 Q(ute consists of the string containing the te)-.2 E (xt matched by the corresponding pattern.)-.15 E (The user himself may also refer to the matched te)108 472.8 Q (xt by using the sequence)-.15 E F2(**)2.5 E F0 5(.T)C(hus)-5 E F2("f) 144 489.6 Q 15(oo" B)-.25 F(AR)-.3 E("f)144 513.6 Q 15(oo" B)-.25 F 10 (AR {)-.3 F(** })2.5 E("f)144 537.6 Q 15(oo" B)-.25 F 10(AR {)-.3 F("f) 2.5 E(oo" })-.25 E F0(all ha)108 561.6 Q .3 -.15(ve t)-.2 H (he same meaning.).15 E -1.1(Yo)108 585.6 S 3.463(uc)1.1 G .963 (an use a)-3.463 F F2(|)3.463 E F0 .963(sign as a tok)3.463 F .962 (en name; this signals that the current re)-.1 F .962(gular e)-.15 F .962(xpression has the same tok)-.15 F(en)-.1 E .13 (name \(and also the same attrib)108 597.6 R .13(ute\) as the tok)-.2 F .13(en speci\214ed in the follo)-.1 F .13 (wing line \(empty lines are ignored\). An)-.25 F(attrib)108 609.6 Q .395(ute de\214nition behind a)-.2 F F2(|)2.895 E F0 .395(is ille)2.895 F -.05(ga)-.15 G 2.894(l. Ho).05 F(we)-.25 E -.15(ve)-.25 G 2.894(ry).15 G .394(ou may specify re)-2.894 F .394(gular e)-.15 F .394 (xpressions with neither a tok)-.15 F(en)-.1 E(name nor an attrib)108 621.6 Q(ute to gi)-.2 E .3 -.15(ve a d)-.25 H(ef).15 E (ault rule or to eat up whitespace.)-.1 E .836 (The declarations and the tok)108 645.6 R .836 (en de\214nitions must be separated by a line containing only the tw)-.1 F 3.337(oc)-.1 G(haracters)-3.337 E F2(%%)108 657.6 Q F0(.)A F2 (Examples)87 686.4 Q F0(The follo)108 698.4 Q(wing e)-.25 E (xamples are all le)-.15 E -.05(ga)-.15 G 2.5(lt).05 G(ok)-2.5 E (en de\214nitions:)-.1 E F2 25([0-9] DIGIT)144 715.2 R F0 (March 13, 1998)274.2 768 Q(2)197.2 E EP %%Page: 3 3 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R/F1 10 /Times-Bold@0 SF 30("{" OPEN)144 84 R 2.5({")27.5 G(\\\\{" indent f)-2.5 E(or)-.25 E(ce })-.18 E 2.5([a-z][a-z0-9]* ID)144 108 R 2.5({")32.5 G ({\\\\it " ** "}" })-2.5 E 12.5("function" |)144 132 R("pr)144 156 Q (ocedur)-.18 E 10(e" PR)-.18 F(OC_INTR)-.3 E 12.5(O{)-.3 G(big_f)-10 E (or)-.25 E(ce + ** })-.18 E([\\t\\ \\n])144 180 Q(|)20 E(.)144 204 Q (The f)87 220.8 Q(ormatted grammar \214le)-.25 E F0 1.181(In the format\ ted grammar \214le the user encodes the general prettyprinting grammar \ for the programming)108 232.8 R 1.059 (language. This is done by specifying a conte)108 244.8 R 1.06 (xt free grammar of the language and by adding information)-.15 F (about the creation of ne)108 256.8 Q 2.5(wa)-.25 G(ttrib)-2.5 E (utes in e)-.2 E -.15(ve)-.25 G(ry rule.).15 E (Its general outline looks lik)5 E 2.5(et)-.1 G(his:)-2.5 E/F2 10 /Times-Italic@0 SF(tok)144 280.8 Q(en declar)-.1 E(ations)-.15 E F1(%%) 144 304.8 Q F2(gr)144 328.8 Q(ammar rules)-.15 E F0(The)108 352.8 Q F2 (tok)2.727 E .227(en declar)-.1 F(ations)-.15 E F0 .227 (section may be empty and the separator between the tw)2.727 F 2.726(op) -.1 G .226(arts of the \214le)-2.726 F F1(%%)2.726 E F0(must)2.726 E (appear unindented on a single line by itself.)108 364.8 Q(The)108 388.8 Q F2(gr)2.885 E .385(ammar rules)-.15 F F0 .386 (section contains the collection of rules of the conte)2.886 F .386 (xt free grammar that can be accom-)-.15 F 1.133(panied by an attrib)108 400.8 R 1.133(ute de\214nition.)-.2 F 3.633(Ar)6.133 G 1.133 (ule is speci\214ed by stating the resulting tok)-3.633 F 1.132 (en, a colon and then the)-.1 F .302(series of tok)108 412.8 R .302(ens\ which will be reduced by this rule. The rule is ended by a semicolon. \ A block de\214nition in)-.1 F -.15(Pa)108 424.8 S(scal for e).15 E (xample might look lik)-.15 E 2.5(et)-.1 G(his:)-2.5 E F1 (block : BEGIN stmt_list END ;)149 448.8 Q F0 -.15(Fo)108 472.8 S(llo) .15 E .845(wing the tok)-.25 F .845 (en list on the right side of the colon can be an attrib)-.1 F .844 (ute de\214nition; this de\214nition states,)-.2 F(ho)108 484.8 Q 2.5 (wt)-.25 G (he translation of the produced symbol is obtained from the tok)-2.5 E (ens on the right side of the rule.)-.1 E .287(An attrib)108 508.8 R .287(ute de\214nition is brack)-.2 F .288(eted amidst curling brack)-.1 F(ets)-.1 E F1({)2.788 E F0(and)2.788 E F1(})2.788 E F0 .288(and can ag) 2.788 F .288(ain consist of strings \(in dou-)-.05 F .074 (ble quotes\), format commands or C code \(enclosed in angled brack)108 520.8 R(ets)-.1 E F1([)2.574 E F0(and)2.574 E F1(])2.574 E F0 2.574(,s)C .074(ee belo)-2.574 F .073(w\) joined together by)-.25 F .096 (an optional)108 532.8 R F1(+)2.596 E F0 5.096(.B)C .096 (ut here you can also refer to the attrib)-5.096 F .096(utes of the tok) -.2 F .096(ens on the right side of the rule. This is)-.1 F .239 (done in a slightly a)108 544.8 R(wkw)-.15 E .239 (ard notation with a number that is preceded with a)-.1 F F1($)2.739 E F0 .239(dollar sign. The numbers refer)2.739 F .384(to the order of app\ earance of the symbols on the right side of the rule. So)108 556.8 R F1 ($1)2.885 E F0 .385(refers to the \214rst tok)2.885 F .385(en of the)-.1 F(rule,)108 568.8 Q F1($2)2.5 E F0(to the second, and so on.)2.5 E(Ag) 108 592.8 Q(ain attrib)-.05 E(ute de\214nitions are allo)-.2 E (wed to span se)-.25 E -.15(ve)-.25 G (ral lines and strings must be speci\214ed in C manner).15 E(.)-.55 E .85(The attrib)108 616.8 R .85 (ute de\214nition may be omitted. If this is so, pretzel will by def)-.2 F .85(ault form the attrib)-.1 F .85(ute of the pro-)-.2 F .681 (duced symbol from the simple concatenation of the attrib)108 628.8 R .681(utes on the right side of the rule.)-.2 F .682(Of course you)5.681 F .615(may also ha)108 640.8 R .915 -.15(ve e)-.2 H .614(mpty right sid\ es of a rule \(to produce things out of nothing\) or simply concatenate\ tw).15 F 3.114(oo)-.1 G(r)-3.114 E (more rules resulting in the same symbol with a)108 652.8 Q F1(|)2.5 E F0(.)A -.15(Fo)108 676.8 S 2.834(re).15 G -.15(ve)-3.084 G .334 (ry terminal tok).15 F .334(en that appears in the grammar rules a spec\ ial line has to be written into the declara-)-.1 F (tions section of the \214le. These de\214nitions are of the form)108 688.8 Q F1(%tok)144 712.8 Q(en)-.1 E F2(tok)2.5 E(enname)-.1 E F0 (March 13, 1998)274.2 768 Q(3)197.2 E EP %%Page: 4 4 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R (It is v)108 84 Q(ery important not to for)-.15 E(get this.)-.18 E/F1 10 /Times-Bold@0 SF(Examples)87 100.8 Q F0 -.15(Fo)108 112.8 S 2.521(re).15 G .021(xample, here ag)-2.671 F .021 (ain is the possible de\214nition of a block in P)-.05 F .02(ascal, no) -.15 F 2.52(ww)-.25 G .02(ith an e)-2.52 F .02(xample attrib)-.15 F .02 (ute de\214ni-)-.2 F(tion:)108 124.8 Q F1(block : BEGIN stmt_list END) 149 148.8 Q 2.5({$)7.5 G 2.5(1$)-2.5 G 2.5(2f)-2.5 G(or)-2.75 E (ce $3 } ;)-.18 E F0 .717(The attrib)108 172.8 R .717(ute of a)-.2 F/F2 10/Times-Italic@0 SF(bloc)3.217 E(k)-.2 E F0 .718 (will therefore consist of the attrib)3.217 F .718(utes of the)-.2 F F1 (BEGIN)3.218 E F0(and)3.218 E F1(stmt_list)3.218 E F0(tok)3.218 E .718 (ens, joined)-.1 F(together with a)108 184.8 Q F2(for)2.5 E(ce)-.37 E F0 (command and the translation of the)2.5 E F1(END)2.5 E F0(tok)2.5 E(en.) -.1 E(These tw)108 208.8 Q 2.5(ol)-.1 G(ines mean the same:)-2.5 E F1 (stmt : block SEMI ;)144 232.8 Q(stmt : block SEMI)144 256.8 Q 2.5({$) 17.5 G 2.5(1$)-2.5 G 2.5(2};)-2.5 G F0(These are le)108 280.8 Q -.05(ga) -.15 G 2.5(lr).05 G(ules too:)-2.5 E F1 5(stmt_list :)144 304.8 R 2.5 ({f)55 G(or)-2.75 E(ce })-.18 E 2.5(|s)174 316.8 S(tmt_list stmt SEMI) -2.5 E 2.5({$)5 G 2.5(1$)-2.5 G 2.5(2$)-2.5 G 2.5(3f)-2.5 G(or)-2.75 E (ce };)-.18 E(Comments and Code)87 333.6 Q F0 .076(There is a v)108 345.6 R .076(ery simple w)-.15 F .076 (ay of putting comments into the formatted tok)-.1 F .076 (en and formatted grammar \214les. This)-.1 F .348(is done in a C++ kin\ d of manner by preceding the comment with a double slash)108 357.6 R F1 (//)2.849 E F0 5.349(.A)C .349(ll characters between)-5.349 F (this sign and the end of the line are ignored by pretzel.)108 369.6 Q .673(In both \214les you can put additional C/C++ code before and after\ the de\214nitions/grammar sections.)108 393.6 R .673(If you)5.673 F -.1 (wa)108 405.6 S .056 (nt to insert code at the end of your \214le, you ha).1 F .356 -.15 (ve t)-.2 H 2.556(op).15 G .056(ut a second)-2.556 F F1(%%)2.556 E F0 .056(on a line by itself and put the code)2.556 F .885(behind it. C/C++\ code before the de\214nitions/rules section has to be tied in with a) 108 417.6 R F1(%{)3.384 E F0(,)A F1(%})3.384 E F0(pair)3.384 E 3.384(.I) -.55 G(nserting)-3.384 E -.15(ex)108 429.6 S (tra code is interesting for people who w).15 E (ant to access it from within the attrib)-.1 E(ute de\214nition.)-.2 E F1(Code within attrib)87 458.4 Q(ute de\214nitions)-.2 E F0 .8(From v) 108 470.4 R .8(ersion 2.0 onw)-.15 F .8(ards pretzel allo)-.1 F .801 (ws to insert C++ code into attrib)-.25 F .801 (ute de\214nitions. This is ho)-.2 F 3.301(wp)-.25 G(retzel)-3.301 E -.15(ex)108 482.4 S (pects you to write code inside your pretzel input \214les:).15 E .837 (Code fragments are brack)108 506.4 R .837(eted within angled brack)-.1 F .837(ets. An)-.1 F 3.337(ya)-.15 G .837(ngled brack)-3.337 F .836 (ets that appear within the C code)-.1 F 1.653(must be escaped with a b\ ackslash. There can blocks of code before and behind the attrib)108 518.4 R 1.654(ute de\214nition)-.2 F .492(which are called)108 530.4 R F1 .492(starting code)2.992 F F0(and)2.991 E F1(ending)2.991 E F0(code)A F1(.)A F0 .491(Only one starting or ending code block is allo)5.491 F 2.991(wed. Both)-.25 F .919(are totally optional, b)108 542.4 R .919 (ut if you w)-.2 F .919(ant to specify either or)-.1 F 3.42(,y)-.4 G .92 (ou need an attrib)-3.42 F .92(ute de\214nition. Starting code is)-.2 F -.15(exe)108 554.4 S .716(cuted before the attrib).15 F .716 (ute of the ne)-.2 F 3.215(wt)-.25 G(ok)-3.215 E .715(en is b)-.1 F .715 (uilt, ending code is e)-.2 F -.15(xe)-.15 G .715(cuted after b).15 F .715(uilding the attrib)-.2 F(ute)-.2 E (and before returning to the calling function \(in the scanner\).)108 566.4 Q 3.144(Code parts within attrib)108 590.4 R 3.144 (ute de\214nitions must return a pointer to an)-.2 F F1(Attrib)5.644 E (ute)-.2 E F0 3.144(class object \(see \214le)5.644 F F1(attr/attr)108 602.4 Q(.nw)-1 E F0 .14(in the pretzel distrib)2.64 F .14 (ution for details\).)-.2 F -.4(Wi)5.139 G .139(thin the formatted tok) .4 F .139(en \214le, the matched te)-.1 F .139(xt is visi-)-.15 F .352 (ble to you in form of a)108 614.4 R F1 .352(char* yytext)2.852 F F0 -.25(va)2.852 G .353(riable. The symbolic names of the tok).25 F .353 (ens are a)-.1 F -.25(va)-.2 G .353(ilable by the same).25 F 1.287 (name that pretzel gi)108 626.4 R -.15(ve)-.25 G 3.787(st).15 G 3.787 (hem. Starting)-3.787 F 1.287(code, code within attrib)3.787 F 1.286 (ute de\214nitions and ending code is totally)-.2 F .878 (optional. But at an)108 638.4 R 3.378(yp)-.15 G .878(lace where the) -3.378 F 3.378(ya)-.15 G .878(re allo)-3.378 F .878(wed, only one brack) -.25 F .879(eted code bit may be placed. Here')-.1 F 3.379(sa)-.55 G(n) -3.379 E -.15(ex)108 650.4 S(ample from the formatted grammar \214le:) .15 E F1(id : ID)144 674.4 Q 2.5({[)5 G(lookup\($1\) ? cr)-2.5 E (eate\("{\\\\bf "\) :)-.18 E(cr)179 691.2 Q (eate\("{\\\\it "\)] $1 "}" };)-.18 E F0 .288(This e)108 715.2 R .288 (xample sho)-.15 F .288(ws ho)-.25 F 2.788(wt)-.25 G 2.788(of)-2.788 G .288(ormat an identi\214er depending on whether it is in a lookup table\ or not. Identi-)-2.788 F(\214ers could be installed in the table for e) 108 727.2 Q(xample lik)-.15 E 2.5(et)-.1 G(his:)-2.5 E(March 13, 1998) 274.2 768 Q(4)197.2 E EP %%Page: 5 5 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R/F1 10 /Times-Bold@0 SF(typedef : TYPEDEF_LIKE INT_LIKE ID)144 84 Q 2.5([i) 171.5 100.8 S(nstall\($3\); ])-2.5 E 2.5({$)171.5 117.6 S 2.5(1$)-2.5 G 2.5(2")-2.5 G({\\\\bf " $3 "}" };)-2.5 E F0 .393(More e)108 141.6 R .393 (xamples can be found in the Pretzelbook. Common routines to escape ide\ nti\214ers, to b)-.15 F .394(uild and man-)-.2 F .893 (age lookup tables, to con)108 153.6 R -.15(ve)-.4 G .892 (rt to and from).15 F F1(Attrib)3.392 E(ute*)-.2 E F0 .892 (or to output deb)3.392 F .892(ug information can be found in the)-.2 F (\214les belonging to the C prettyprinter in the directory)108 165.6 Q F1(languages/cee)2.5 E F0(of the pretzel distrib)2.5 E(ution.)-.2 E F1 (The set of f)87 194.4 Q(ormat commands)-.25 E F0(Here')108 206.4 Q 2.5 (sal)-.55 G (ist of the format commands supported by pretzel and their meaning:)-2.5 E/F2 10/Times-Italic@0 SF(null)108 218.4 Q F0(empty command.)20.44 E F2 (indent)108 230.4 Q F0(indents the ne)11 E(xt line a little more.)-.15 E F2(outdent)108 242.4 Q F0(tak)6 E (es back the last indentation \(de-indent\).)-.1 E F2(for)108 254.4 Q (ce)-.37 E F0(forces a line break.)15.82 E F2(br)108 266.4 Q(eak_space) -.37 E F0(denotes a possible space for a line break.)144 278.4 Q F2 (opt1)108 290.4 Q F0(...)A F2(opt9).23 E F0 .134(denotes an optional li\ ne break with the continuation line indented a litte with respect to th\ e normal)144 302.4 R(starting position.)144 314.4 Q F2(bac)108 326.4 Q (kup)-.2 E F0(denotes a small backspace.)7.32 E F2(big_for)108 338.4 Q (ce)-.37 E F0(forces a line break and inserts a little e)144 350.4 Q (xtra space.)-.15 E F2(no_indent)108 362.4 Q F0 (causes the current line to be output \215ushleft.)144 374.4 Q F2 (cancel)108 386.4 Q F0 .143(obliterates an)9.9 F(y)-.15 E F2(br)2.643 E (eak_space)-.37 E F0(,).18 E F2(opt)2.643 E F0(,).68 E F2(for)2.643 E (ce)-.37 E F0(or)2.643 E F2(big_for)2.643 E(ce)-.37 E F0 .142 (command that immediatly precedes or follo)2.642 F(ws)-.25 E (it and also cancels an)144 398.4 Q(y)-.15 E F2(bac)2.5 E(kup)-.2 E F0 (command that follo)2.5 E(ws it.)-.25 E -.15(Fo)144 422.4 S 4.93(rac).15 G 2.43(omplete reference on ho)-4.93 F 4.931(wt)-.25 G 4.931(ow)-4.931 G 2.431(rite pretzel input, look into the Pretzelbook which is)-4.931 F (included in the pretzel distrib)144 434.4 Q(ution.)-.2 E F1 -.25(Fo)87 451.2 S(rmat command pr).25 E(epr)-.18 E(ocessing)-.18 E F0 (The format commands are preprocessed according to the follo)108 463.2 Q (wing tw)-.25 E 2.5(or)-.1 G(ules:)-2.5 E(1. A sequence of consecuti)108 492 Q -.15(ve)-.25 G F2(br)144 504 Q(eak_space)-.37 E F0(,).18 E F2(for) 3.253 E(ce)-.37 E F0 3.253(,a).18 G(nd/or)-3.253 E F2(big_for)3.253 E (ce)-.37 E F0 .752 (commands is replaced by a single command \(the maximum)3.253 F (of the gi)144 516 Q -.15(ve)-.25 G 2.5(no).15 G(nes\).)-2.5 E(2. The) 108 532.8 Q F2(cancel)10.45 E F0 .446(command cancels an)2.946 F(y)-.15 E F2(br)2.946 E(eak_space)-.37 E F0(,).18 E F2(opt)2.947 E F0(,).68 E F2 (for)2.947 E(ce)-.37 E F0(or)2.947 E F2(big_for)2.947 E(ce)-.37 E F0 .447(command that immediatly pre-)2.947 F(cede or follo)144 544.8 Q 2.5 (wi)-.25 G 2.5(ta)-2.5 G(nd also cancels an)-2.5 E(y)-.15 E F2(bac)2.5 E (kup)-.2 E F0(command that follo)2.5 E(ws it.)-.25 E/F3 9/Times-Bold@0 SF(THE OUTPUT FILES)72 573.6 Q F0 .286(If pretzel runs without error)108 585.6 R 2.786(,y)-.4 G .286(ou will obtain the de\214nition of a C++ pr\ ettyprinter class in form of tw)-2.786 F 2.785<6f8c>-.1 G(les.)-2.785 E .575(The \214rst \214le is a v)108 597.6 R(alid)-.25 E F1(bison\(1\)) 3.075 E F0 .576(\214le from which the actual prettyprinting parser clas\ s can be obtained. The)3.075 F .312 (second \214le \(generated from the formatted tok)108 609.6 R .312 (en \214le\) can be processed with the)-.1 F F1(\215ex\(1\))2.812 E F0 .311(scanner generator to)2.812 F (form the prettyprinting scanner class used by the parser)108 621.6 Q(.) -.55 E F1(The bison \214le)87 638.4 Q F0 .053(The generated bison \214l\ e contains the de\214nitions for a prettyprinting parser class that is \ a subclass of the fol-)108 650.4 R(lo)108 662.4 Q (wing abstract base class \(contained in the \214le)-.25 E F1(Pparse.h) 2.5 E F0(within the pretzel include directory\):)2.5 E F1 (#include)-.18 E(#include"attr)144 703.2 Q(.h") -1 E(#include"output.h")144 720 Q F0(March 13, 1998)274.2 768 Q(5)197.2 E EP %%Page: 6 6 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R/F1 10 /Times-Bold@0 SF(class Pparse {)144 84 Q(public:)144 100.8 Q (Pparse\(\) {};)180 112.8 Q(~Pparse\(\) {};)180 129.6 Q(virtual int pr) 180 153.6 Q(ettyprint\(istr)-.18 E(eam*, ostr)-.18 E(eam*\) = 0;)-.18 E (virtual int pr)180 177.6 Q(ettyprint\(istr)-.18 E(eam*, Output*\) = 0;) -.18 E(};)144 189.6 Q F0 (The prettyprinter generated by pretzel will be a subclass of the follo) 108 213.6 Q(wing form:)-.25 E F1 (#include Pparse.h // include abstract base class)144 237.6 Q(class PP) 144 261.6 Q(ARSE_N)-.74 E(AME : public Pparse {)-.2 E(public:)144 285.6 Q(PP)180 297.6 Q(ARSE_N)-.74 E(AME\(\); ~PP)-.2 E(ARSE_N)-.74 E (AME\(\);)-.2 E(int pr)180 321.6 Q(ettyprint\(istr)-.18 E(eam*, ostr) -.18 E(eam*\);)-.18 E(int pr)180 345.6 Q(ettyprint\(istr)-.18 E (eam*, Output*\);)-.18 E -.1(vo)180 369.6 S(id deb).1 E(ug_on\(\); v)-.2 E(oid deb)-.1 E(ug_off\(\);)-.2 E(};)144 381.6 Q F0 .479(The name of th\ e class may be changed by rede\214ning the preprocessor macro)108 405.6 R F1(PP)2.979 E(ARSE_N)-.74 E(AME)-.2 E F0 .479(within the)2.979 F 1.738 (formatted grammar \214le. The actual prettyprinting function is)108 417.6 R F1(pr)4.238 E(ettyprint)-.18 E F0 1.738(that reads te)4.238 F 1.738(xt from an input)-.15 F .657(stream \(i.e. a C++)108 429.6 R F1 (istr)3.156 E(eam)-.18 E F0 .656 (object\) and outputs the results to an output stream \(i.e. a C++)3.156 F F1(ostr)3.156 E(eam)-.18 E F0(object,)3.156 E(see)108 441.6 Q F1 (ios\(3C++\))3.501 E F0 3.501(\). The)B 1.001(second o)3.501 F -.15(ve) -.15 G 1.001(rloaded v).15 F 1.001(ersion of)-.15 F F1(pr)3.501 E (ettyprint)-.18 E F0(tak)3.501 E 1.001(es an)-.1 F F1(Output)3.501 E F0 1.002(object \(see the \214le)3.502 F F1(out-)3.502 E(put/output.nw)108 453.6 Q F0 .747(and the Pretzelbook in the pretzel distrib)3.247 F .746 (ution for details\) and uses this to output the pret-)-.2 F (typrinted code. The)108 465.6 Q F1(deb)2.5 E(ug)-.2 E F0 (functions can be used to turn deb)2.5 E(ugging output to)-.2 E F1(cerr) 2.5 E F0(on and of)2.5 E(f.)-.25 E F1(The \215ex \214le)87 494.4 Q F0 .617(The prettyprinting parser class relies on the service of a prettyp\ rinting scanner that can be produced using)108 506.4 R .224(the second \ pretzel \214le. It contails a complete de\214nition of a scanner subcla\ ss of this abstract base class \(see)108 518.4 R(\214le)108 530.4 Q F1 (Pscan.h)2.5 E F0(in the pretzel include directory\):)2.5 E F1 (#include #include"attr)-.18 E(.h")-1 E (class Pscan {)144 578.4 Q(public:)144 602.4 Q(Pscan\(istr)180 614.4 Q (eam*\) {}; ~Pscan\(\) {};)-.18 E(virtual int scan\(Attrib)180 638.4 Q (ute**\) = 0;)-.2 E(};)144 650.4 Q F0 1.312 (The scanner must be initialized with a C++)108 674.4 R F1(istr)3.812 E (eam)-.18 E F0 1.312(pointer from which it tak)3.812 F 1.312 (es its input. A call to the)-.1 F(actual)108 686.4 Q F1(scan)2.906 E F0 .406(function returns an inte)2.906 F .406(ger \(the tok)-.15 F .406 (en code of the tok)-.1 F .406 (en just scanned or 0 on end-of-\214le\) plus a)-.1 F .368 (call by reference attrib)108 698.4 R .369 (ute containing the contents of the tok)-.2 F .369(en \(see \214le)-.1 F F1(attr/attr)2.869 E(.nw)-1 E F0 .369(from the pretzel distri-)2.869 F -.2(bu)108 710.4 S(tion\).).2 E(March 13, 1998)274.2 768 Q(6)197.2 E EP %%Page: 7 7 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 387.76(pretzel\(1\) pretzel\(1\))72 48 R (The produced prettyprinting scanner class is a subclass and looks lik) 108 84 Q 2.5(et)-.1 G(his:)-2.5 E/F1 10/Times-Bold@0 SF (#include Pscan.h // include abstract base class)144 108 Q (class PSCAN_N)144 132 Q(AME : public Pscan {)-.2 E(public:)144 156 Q (PSCAN_N)180 168 Q(AME\(istr)-.2 E(eam*\);)-.18 E(~PSCAN_N)180 192 Q (AME\(\);)-.2 E(int scan\(Attrib)180 216 Q(ute**\);)-.2 E F0 .253 (The name of the scanner can be changed within the formatted tok)108 240 R .253(en \214le by rede\214ning the)-.1 F F1(PSCAN_N)2.753 E(AME)-.2 E F0 .968(macro within the declarations section. The scanner class e)108 252 R .968(xpects to \214nd tok)-.15 F .968 (en de\214nitions common to the)-.1 F .155 (scanner and the parser in a \214le called)108 264 R F1(ptokdefs.h)2.655 E F0 .155(and will try to include this \214le. Y)2.655 F .155 (ou either ha)-1.1 F .455 -.15(ve t)-.2 H 2.655(op).15 G(ro)-2.655 E (vide)-.15 E .809(this \214le yourself or use the)108 276 R F1(-d)3.309 E F0 .81 (option of Bison to create one that \214ts a formatted grammar \(see) 3.309 F F1(bison\(1\))3.31 E F0(\).)A -1.1(Yo)108 288 S 4.246(um)1.1 G 1.746(ay change the name of the \214le that the scanner e)-4.246 F 1.746 (xpects by rede\214ning the)-.15 F F1(PT)4.246 E(OKDEFS_N)-.18 E(AME)-.2 E F0 1.143(macro in the declarations section of the formatted tok)108 300 R 1.143(en \214le.)-.1 F 1.143 (Commen header \214les for the abstract base)6.143 F (classes and the def)108 312 Q (ault subclasses reside in the pretzel include directory)-.1 E(.)-.65 E /F2 9/Times-Bold@0 SF(FILES)72 340.8 Q F1(/usr/local/lib/pr)108 352.8 Q (etzel/libpr)-.18 E(etzel.a)-.18 E F0(pretzel runtime library)13.97 E(.) -.65 E F1(/usr/local/lib/pr)108 364.8 Q(etzel/include)-.18 E F0(directo\ ry for runtime library include \214les \(pretzel include directory\).) 30.72 E F1(/usr/local/lib/pr)108 376.8 Q(etzel/include/Pscan.h)-.18 E (/usr/local/lib/pr)108 388.8 Q(etzel/include/Pparse.h)-.18 E F0 (headers for abstract base \214les.)258 400.8 Q F1(/usr/local/lib/pr)108 412.8 Q(etzel/include/Ppscan.h)-.18 E(/usr/local/lib/pr)108 424.8 Q (etzel/include/Ppparse.h)-.18 E F0(def)258 436.8 Q (ault headers for generated subclasses.)-.1 E F1(/usr/local/lib/pr)108 448.8 Q(etzel/pr)-.18 E(etzel-latex.sty)-.18 E F0(LaT)258 460.8 Q (eX style to typeset pretzel output.)-.7 E F1(/usr/local/lib/pr)108 472.8 Q(etzel/pascal.ft)-.18 E(/usr/local/lib/pr)108 484.8 Q (etzel/pascal.fg)-.18 E F0 -.15(ex)24.34 G(ample input \214les to mak) .15 E 2.5(eap)-.1 G(ascal compiler)-2.5 E(.)-.55 E F2(SEE ALSO)72 501.6 Q F0(pretzel-it\(1\), \215e)108 513.6 Q(x\(1\), bison\(1\))-.15 E/F3 10 /Times-Italic@0 SF(The Pr)108 525.6 Q(etzelBook, second edition)-.37 E F0 2.52.5 G (ltimate source of information, included in the pretzel distrib)-2.5 E (ution.)-.2 E(The Pretzel homepage on the WWW at)108 537.6 Q F1 (http://www)2.5 E(.iti.inf)-.7 E(ormatik.tu-darmstadt.de/~gaertner/pr) -.25 E(etzel)-.18 E F2 -.45(AU)72 554.4 S(THOR).45 E F0(Felix Gaertner) 108 566.4 Q 2.5(,e)-.4 G(mail: fcg@acm.or)-2.5 E(g)-.18 E (March 13, 1998)274.2 768 Q(7)197.2 E EP %%Trailer end %%EOF pretzel-2.0n-2/man/index.list0000644000000000000000000000041506502165606014640 0ustar rootrootthis directory & manual pages for Pretzel and pretzel-it Makefile & the Makefile pretzel-it.1 & manpage for pretzel-it pretzel.1 & manpage for Pretzel pretzel.1.ps & manpage for pretzel in postscript format pretzel-it.1.ps & manpage for pretzel-it in postscript format pretzel-2.0n-2/man/index.html0000644000000000000000000000202706502165613014630 0ustar rootroot Index file for directory "" of Pretzel distribution

Index file for directory "" of Pretzel distribution

Files and directories are:

this directory

    manual pages for Pretzel and pretzel-it
Makefile
    the Makefile
pretzel-it.1
    manpage for pretzel-it
pretzel.1
    manpage for Pretzel
pretzel.1.ps
    manpage for pretzel in postscript format
pretzel-it.1.ps
    manpage for pretzel-it in postscript format

Felix Gaertner

To Pretzel Homepage.

Last modified: Fri Mar 13 09:17:16 MET 1998 pretzel-2.0n-2/man/Makefile0000644000000000000000000000103606502165522014271 0ustar rootroot# $Id: Makefile,v 1.1 1998/03/13 08:16:18 gaertner Exp $ #---------------------------------------------------------------------- # # Makefile for pretzel and pretzel-it manpages # # have a look at both -- I forgot the line :-( pretzel: nroff -man pretzel.1 | less pretzel.1.ps: pretzel.1 groff -man pretzel.1 > pretzel.1.ps pretzel-it: nroff -man pretzel-it.1 | less pretzel-it.1.ps: pretzel-it.1 groff -man pretzel-it.1 > pretzel-it.1.ps # DO NOT USE WHEN INSTALLING release: cp pretzel-it.1 pretzel.1 /users/gaertner/man/man1 pretzel-2.0n-2/man/pretzel.10000644000000000000000000004256310765025502014411 0ustar rootroot.\" $Id: pretzel.1,v 2.3 1998/03/13 08:15:41 gaertner Exp $ .\" manpage for Pretzel! .TH pretzel 1 "June 11, 1998" .ds ]W Release 2.0k: June 1998 .SH NAME pretzel \- the universal prettyprinter generator .SH SYNOPSIS pretzel [-qtgdh] [-o outfile] fileprefix pretzel [-qtgdh] [-o outfile] file1 file2 .PD .SH DESCRIPTION Pretzel is a program that generates a prettyprinter module from a formal description of the way a certain language should be prettyprinted. A .B prettyprinter is a function or program that rearranges source code to enhance its readability. Prettyprinters generated by pretzel output LaTeX source code that can be used within your own documents. NB that pretzel produces .BR modules , not programs! You have to provide two input files to pretzel that specify the way given source code should be prettyprinted. These two files are called the .B formatted token file (suffix .BR .ft ) and the .B formatted grammar file (suffix .BR .fg ). From this input, pretzel generates two things: a valid .B flex(1) file that forms the .B prettyprinting scanner and a valid .B bison(1) input file that can be used to build the .B prettyprinting parser (which is the actual prettyprinter). There is a shell script .B pretzel-it that faciliates using pretzel (see .BR pretzel-it(1) ). This man page is only meant as a quick reference to pretzel usage. Look into the main documentation of pretzel if you are new to all this. .SS "Invoking pretzel" Invoking pretzel can take two forms: Either invoke it specifying only the common prefix of the two input files, or specify both files seperately on the command line. If you specify both files, the formatted token file comes first. .SS "Examples" Say your input files are called .B foo.ft and .BR foo.fg . Then you can say .PP .RS .B pretzel foo .RE .PP to invoke pretzel properly. If your files are called .B foo.ft and .B bar.fg then you would have to say .PP .RS .B pretzel foo.ft bar.fg .RE .PP to do the job. .SH OPTIONS Pretzel recognizes the following options: .RS .TP .B -q Run quietly. .TP .B -t Process formatted token file only. .TP .B -g Process formatted grammar file only (options .B -t and .B -g are mutually exclusive). .TP .B -d Print debug information to the screen. .TP .B -h Print full usage message. .TP .B -o name Use .B name as prefix of the generated output files. .RE .SH "THE INPUT FILES" This section summarizes the format of the input files and the .B format command primitives that pretzel supports. .SS "The formatted token file" The formatted token file contains a list of token definitions with their corresponding "prettyprinted" form. The prettyprinted form of a token will be called an .B attribute or a .BR translation . The general outline of the formatted token file is .PP .RS .I declarations %% .I token definitions .RE Normally, the .I declarations part is empty. You can put a general description of the file here (as a C comment) and redefinitions of the default interface go here as well. The .I token definitions section of the formatted token file contains a series of token definitions of the form: .PP .RS .I pattern token attribute .RE The .I pattern must be a valid regular expression (in terms of .BR flex(1) ) and must be unindented. The .I token specifies the symbolic name of the token for the pattern and begins at the first non-whitespace character after the pattern. The token name must be a legal name for an identifier in Pascal notation and .B must be all in upper case. (Underlines are allowed but not at the beginning of a word.) The .I attribute for this token, that is it's prettyprinted form, consists of all text between the two curling brackets .B { and .BR } . Attributes can be either simple strings (surrounded by double quotes), format commands (see below), your own C++ code (enclosed in angled brackets .B [ and .BR ] , see below) or a combination of both joined together by an optional .B + sign. Attribute definitions can cover several lines and the starting .B { needn't stand on the same line as the token definition; however subsequent lines must be indented with at least one blank or one tab. If you define strings as part of an attribute definition, you have to specify them in a C kind of fashion, i.e. you can insert newlines and tabs with .B \en and .BR \et . But if you want to insert a backslash into a string, you mustn't forget to put two backslashes .B \e\e into the input file. This is especially noteworthy if you are using TeX as typesetter. If the definition of the attribute is omitted pretzel creates an attribute for this pattern by default. The default attribute consists of the string containing the text matched by the corresponding pattern. The user himself may also refer to the matched text by using the sequence .BR ** . Thus .PP .RS .B "foo" BAR .B "foo" BAR { ** } .B "foo" BAR { "foo" } .RE all have the same meaning. You can use a .B | sign as a token name; this signals that the current regular expression has the same token name (and also the same attribute) as the token specified in the following line (empty lines are ignored). An attribute definition behind a .B | is illegal. However you may specify regular expressions with neither a token name nor an attribute to give a default rule or to eat up whitespace. The declarations and the token definitions must be separated by a line containing only the two characters .BR %% . .SS Examples The following examples are all legal token definitions: .PP .RS .B [0-9] DIGIT .B "{" OPEN { "\e\e{" indent force } .B [a-z][a-z0-9]* ID { "{\e\eit " ** "}" } .B "function" | .B "procedure" PROC_INTRO { big_force + ** } .B [\et\e \en] | .B . .RE .SS "The formatted grammar file" In the formatted grammar file the user encodes the general prettyprinting grammar for the programming language. This is done by specifying a context free grammar of the language and by adding information about the creation of new attributes in every rule. Its general outline looks like this: .RS .I token declarations .B %% .I grammar rules .RE The .I token declarations section may be empty and the separator between the two parts of the file .B %% must appear unindented on a single line by itself. The .I grammar rules section contains the collection of rules of the context free grammar that can be accompanied by an attribute definition. A rule is specified by stating the resulting token, a colon and then the series of tokens which will be reduced by this rule. The rule is ended by a semicolon. A block definition in Pascal for example might look like this: .RS .B block : BEGIN stmt_list END ; .RE Following the token list on the right side of the colon can be an attribute definition; this definition states, how the translation of the produced symbol is obtained from the tokens on the right side of the rule. An attribute definition is bracketed amidst curling brackets .B { and .B } and can again consist of strings (in double quotes), format commands or C code (enclosed in angled brackets .B [ and .BR ] , see below) joined together by an optional .BR + . But here you can also refer to the attributes of the tokens on the right side of the rule. This is done in a slightly awkward notation with a number that is preceded with a .B $ dollar sign. The numbers refer to the order of appearance of the symbols on the right side of the rule. So .B $1 refers to the first token of the rule, .B $2 to the second, and so on. Again attribute definitions are allowed to span several lines and strings must be specified in C manner. The attribute definition may be omitted. If this is so, pretzel will by default form the attribute of the produced symbol from the simple concatenation of the attributes on the right side of the rule. Of course you may also have empty right sides of a rule (to produce things out of nothing) or simply concatenate two or more rules resulting in the same symbol with a .BR | . For every terminal token that appears in the grammar rules a special line has to be written into the declarations section of the file. These definitions are of the form .RS .B %token .I tokenname .RE It is very important not to forget this. .SS Examples For example, here again is the possible definition of a block in Pascal, now with an example attribute definition: .RS .B block : BEGIN stmt_list END { $1 $2 force $3 } ; .RE The attribute of a .I block will therefore consist of the attributes of the .B BEGIN and .B stmt_list tokens, joined together with a .I force command and the translation of the .B END token. These two lines mean the same: .RS .B stmt : block SEMI ; .B stmt : block SEMI { $1 $2 } ; .RE These are legal rules too: .RS .B stmt_list : { force } .B | stmt_list stmt SEMI { $1 $2 $3 force }; .RE .SS "Comments and Code" There is a very simple way of putting comments into the formatted token and formatted grammar files. This is done in a C++ kind of manner by preceding the comment with a double slash .BR // . All characters between this sign and the end of the line are ignored by pretzel. In both files you can put additional C/C++ code before and after the definitions/grammar sections. If you want to insert code at the end of your file, you have to put a second .B %% on a line by itself and put the code behind it. C/C++ code before the definitions/rules section has to be tied in with a .BR %{ , .B %} pair. Inserting extra code is interesting for people who want to access it from within the attribute definition. .SS "Code within attribute definitions" From version 2.0 onwards pretzel allows to insert C++ code into attribute definitions. This is how pretzel expects you to write code inside your pretzel input files: Code fragments are bracketed within angled brackets. Any angled brackets that appear within the C code must be escaped with a backslash. There can blocks of code before and behind the attribute definition which are called .B starting code and .BR ending code . Only one starting or ending code block is allowed. Both are totally optional, but if you want to specify either or, you need an attribute definition. Starting code is executed before the attribute of the new token is built, ending code is executed after building the attribute and before returning to the calling function (in the scanner). Code parts within attribute definitions must return a pointer to an .B Attribute class object (see file .B attr/attr.nw in the pretzel distribution for details). Within the formatted token file, the matched text is visible to you in form of a .B char* yytext variable. The symbolic names of the tokens are available by the same name that pretzel gives them. Starting code, code within attribute definitions and ending code is totally optional. But at any place where they are allowed, only one bracketed code bit may be placed. Here's an example from the formatted grammar file: .RS .B id : ID { [lookup($1) ? create("{\e\ebf ") : .PP .B create("{\e\eit ")] $1 "}" }; .RE This example shows how to format an identifier depending on whether it is in a lookup table or not. Identifiers could be installed in the table for example like this: .RS .B typedef : TYPEDEF_LIKE INT_LIKE ID .PP .B [ install($3); ] .PP .B { $1 $2 "{\e\ebf " $3 "}" }; .RE More examples can be found in the Pretzelbook. Common routines to escape identifiers, to build and manage lookup tables, to convert to and from .B Attribute* or to output debug information can be found in the files belonging to the C prettyprinter in the directory .B languages/cee of the pretzel distribution. .SS "The set of format commands" Here's a list of the format commands supported by pretzel and their meaning: .PD 0 .TP .I null empty command. .TP .I indent indents the next line a little more. .TP .I outdent takes back the last indentation (de-indent). .TP .I force forces a line break. .TP .I break_space denotes a possible space for a line break. .TP .IR opt1 ... opt9 denotes an optional line break with the continuation line indented a litte with respect to the normal starting position. .TP .I backup denotes a small backspace. .TP .I big_force forces a line break and inserts a little extra space. .TP .I no_indent causes the current line to be output flushleft. .TP .I cancel obliterates any .IR break_space , .IR opt , .I force or .I big_force command that immediatly precedes or follows it and also cancels any .I backup command that follows it. .PD For a complete reference on how to write pretzel input, look into the Pretzelbook which is included in the pretzel distribution. .SS "Format command preprocessing" The format commands are preprocessed according to the following two rules: .TP 1. A sequence of consecutive .IR break_space , .IR force , and/or .I big_force commands is replaced by a single command (the maximum of the given ones). .TP 2. The .I cancel command cancels any .IR break_space , .IR opt , .I force or .I big_force command that immediatly precede or follow it and also cancels any .I backup command that follows it. .SH "THE OUTPUT FILES" If pretzel runs without error, you will obtain the definition of a C++ prettyprinter class in form of two files. The first file is a valid .B bison(1) file from which the actual prettyprinting parser class can be obtained. The second file (generated from the formatted token file) can be processed with the .B flex(1) scanner generator to form the prettyprinting scanner class used by the parser. .SS "The bison file" The generated bison file contains the definitions for a prettyprinting parser class that is a subclass of the following abstract base class (contained in the file .B Pparse.h within the pretzel include directory): .RS .B #include .PP .B #include"attr.h" .PP .B #include"output.h" .B class Pparse { .PP .B public: .RS .B Pparse() {}; .PP .B ~Pparse() {}; .B virtual int prettyprint(istream*, ostream*) = 0; .B virtual int prettyprint(istream*, Output*) = 0; .RE .B }; .RE The prettyprinter generated by pretzel will be a subclass of the following form: .RS .B #include "Pparse.h" // include abstract base class .B class PPARSE_NAME : public Pparse { .B public: .RS .B PPARSE_NAME(); .B ~PPARSE_NAME(); .B int prettyprint(istream*, ostream*); .B int prettyprint(istream*, Output*); .B void debug_on(); .B void debug_off(); .RE .B }; .RE The name of the class may be changed by redefining the preprocessor macro .B PPARSE_NAME within the formatted grammar file. The actual prettyprinting function is .B prettyprint that reads text from an input stream (i.e. a C++ .B istream object) and outputs the results to an output stream (i.e. a C++ .B ostream object, see .BR ios(3C++) ). The second overloaded version of .B prettyprint takes an .B Output object (see the file .B output/output.nw and the Pretzelbook in the pretzel distribution for details) and uses this to output the prettyprinted code. The .B debug functions can be used to turn debugging output to .B cerr on and off. .SS "The flex file" The prettyprinting parser class relies on the service of a prettyprinting scanner that can be produced using the second pretzel file. It contails a complete definition of a scanner subclass of this abstract base class (see file .B Pscan.h in the pretzel include directory): .RS .B #include .B #include"attr.h" .B class Pscan { .B public: .RS .B Pscan(istream*) {}; .B ~Pscan() {}; .B virtual int scan(Attribute**) = 0; .RE .B }; .RE The scanner must be initialized with a C++ .B istream pointer from which it takes its input. A call to the actual .B scan function returns an integer (the token code of the token just scanned or 0 on end-of-file) plus a call by reference attribute containing the contents of the token (see file .B attr/attr.nw from the pretzel distribution). The produced prettyprinting scanner class is a subclass and looks like this: .RS .B #include "Pscan.h" // include abstract base class .B class PSCAN_NAME : public Pscan { .B public: .RS .B PSCAN_NAME(istream*); .B ~PSCAN_NAME(); .B int scan(Attribute**); .RE .B}; .RE The name of the scanner can be changed within the formatted token file by redefining the .B PSCAN_NAME macro within the declarations section. The scanner class expects to find token definitions common to the scanner and the parser in a file called .B ptokdefs.h and will try to include this file. You either have to provide this file yourself or use the .B -d option of Bison to create one that fits a formatted grammar (see .BR bison(1) ). You may change the name of the file that the scanner expects by redefining the .B PTOKDEFS_NAME macro in the declarations section of the formatted token file. Commen header files for the abstract base classes and the default subclasses reside in the pretzel include directory. .SH FILES .PD 0 .TP 30 .B /usr/lib/pretzel/libpretzel.a pretzel runtime library. .TP .B /usr/include/pretzel directory for runtime library include files (pretzel include directory). .TP .B /usr/local/lib/pretzel/include/Pscan.h .TP .B /usr/include/pretzel/Pparse.h headers for abstract base files. .TP .B /usr/include/pretzel/Ppscan.h .TP .B /usr/include/pretzel/Ppparse.h default headers for generated subclasses. .TP .B /usr/lib/texmf/tex/latex/pretzel/pretzel-latex.sty LaTeX style to typeset pretzel output. .PD .SH "SEE ALSO" .PD 0 pretzel-it(1), flex(1), bison(1) .PP .I "The PretzelBook, second edition" \- ultimate source of information, included in the pretzel distribution. .PP The Pretzel homepage on the WWW at .B http://www.iti.informatik.tu-darmstadt.de/~gaertner/pretzel .PD .SH AUTHOR Felix Gaertner, email: fcg@acm.org pretzel-2.0n-2/man/pretzel-it.1.ps0000644000000000000000000002135006520315271015432 0ustar rootroot÷à0áØè‹ÿÿÿÿóKñ`y@@cmr10«ž´¸pretzel-it(1)‘uppretzel-it(1)Žóò"V @cmbx10¬žpìNAMEŽ«pìž%¤pretzel-itó!",š@@cmsy10­ o« kuse mPretzel nto kbuild ka kprettÿ#yprinÿ"terެž4²SYNOPSISŽ«pìž%¤pretzel-it o[-iqvdnh] llanguage lppnameެž4²DESCRIPTIONŽ«pìž%¤Pretzel-it Ùis Öa Õshell ×script ×that Õusesóò"V@@cmbx10® ×pretzel(1)« mto Ôbuild Ôa Ôsimple ×prettÿ#yprinÿ"ter Õexecutable. ØIt Õmini-Žž%¤mizes€building|a|Pretzelprettÿ#yprinÿ"ter}to|just~one~shellcommand.€See®pretzel(1)«for}a}generalŽž%¤oÿ"vÿ"erview nand ka kdescription nof kthe linput k les.ŽžKHYýeou haÿ"vÿ"e to proÿ"vide the same tÿ"wÿ#o input  les to pretzel-it as to pretzel. These tÿ"wÿ#o  les are calledŽž%¤the® *formatted ¿tokÿen º le« »(sux® +.ft«) +and )the® *formatted ¿grammar ¿ le« ¼(sux® ,.fg«).—Both + lesŽž%¤need to Žhaÿ"vÿ"e the same ‘pre x® Žlanguage«.üFýerom Žthis Žinput, pretzel-it ‘generates ‘an executable ‘pret-Žž%¤tÿ"yprinÿ"ter lcalled® mppname«.Ž®¾!ž4²ExampleŽ«Aßž%¤Saÿ"yýe, ºyÿ"ou ºhaÿ"vÿ"e »written ¼tÿ"wÿ#o º les® ¼foo.ft«Mand® ºfoo.fg«Mthat ºconÿ#tain ºthe »prettÿ#yprinÿ"ting »information ¼forŽž%¤yÿ"our àfaÿ"vÿ"ourite áprogramming âlanguageóý':@@cmti10¯ áfoþho«ú.KTýfo àget àan ßexecutable ãprettÿ#yprinÿ"ter® àfoopp«pfor ßit, ßsim-Žž%¤ply ktÿ"ypÞe:Ž®pìžKHpretzel-it foo üfooppެ‘ÿ(žZVOPTIONSŽ«pìž%¤Pretzel-it ohas lthe lfolloÿ"wing loptions:Ž®pìž4²-i«Z÷Don't kremoÿ$vÿ"e linÿ"termediate oproÞducts mof kpretzeling.Ž®ž4²-q«QûRun lquietlyýf.Ž®ž4²-v«QûVýeerbßose mmoßde, lprinÿ"t kshell mcommands obÞefore minÿ"vÿ"oking k(for kdebugging).Ž®ž4²-d«PûTýfurn Íprettÿ#yprinÿ"ter Îdebugging Îfeatures Ðon Îbÿ"y Îdefault; Ïalso ÏproÞduce Ða Îdetailed Ðdiag-Žpìž%¤nosis le (sux® .output«)that conÿ#tains a detailed analysis of the grammar andŽž%¤pÞossible nproblems nwith lit k(to kease ndebugging lthe lprettÿ#yprinÿ"ting kgrammar).Ž®ž4²-h«PûPrinÿ"t kfull kusage mmessage.Ž®ž4²-n«PûNoÿ"wÿ#eb lmoßde. lSee msection® nInÿterfacing with ýnoÿwÿeb(1)« ÿbÞeloÿ#w.ެ‘ÿ(žúTHE ËGENERAýTTED ËPRETTYPRINTERŽ«pìž%¤The œgenerated executable žwill ›bÞe ›a šprogram ›that šreads œsource coßde ›from ›the ›standard ›input šandŽž%¤will (write )prettÿ#yprinÿ"ted (coßde (to 'the (standard (output. 'The )prettÿ#yprinÿ"ted (coßde (can (bÞe (tÿ"ypÞeset *usingŽ®ž%¤latex« ÿtogether mwith lthe® lpretzel-latex« doÞcumenÿ%t kstÿ#yle.Ž®¾!ž4²ExampleŽ«Aßž%¤Saÿ"yýe, kyÿ"ou khaÿ"vÿ"e lbuilt® kfoopp« üalready land khaÿ"vÿ"e la kscrap mof ksource ncoßde lin ka k le® lbar.foo«.×Tÿ#ypÞeŽ®pìžKHfooppó  b>@@cmmi10° ü<®bar.foo° ü>®bar.texŽ«žKHand”the•prettÿ#yprinÿ"ter•will•prettÿ#yprinÿ"t”the•coßde–and•write—LaTýfeX–coßde–to®•bar.tex«.Týfo•use—thisŽž%¤coßdeOinNyÿ"ourNdoÞcumenÿ%ts,OsimpleQincludePthe®Opretzel-latex«édoÞcumenÿ%tNstÿ#yleNandMincludeOtheN leŽž%¤insideKtheJnew®Kppcode«ÚLaTýfeXJenÿ#vironmenÿ$t.IHere'sLaIminimalLLaTýfeXK leKtoJloÞokJatJtheKpret-Žž%¤tÿ"yprinÿ"ted lcoßde:Ž­pìžKHn®documenstÿyle[pretzel-latex]­f®article­gŽž%¤n®begin­f®documenÿt­gŽž%¤n®begin­f®ppcode­gŽöž%¤n®input­f®foo.tex­gŽ«‘{žxxMarcÿ#h k13, k1998‘eJ1ŽŒ‹«ž´¸pretzel-it(1)‘uppretzel-it(1)Ž­‘áØžpìn®end­f®ppcode­gŽž%¤n®end­f®documenÿt­gެ‘ÿ(žZVINTERFünAÿCING ÌWITH ÌNOÿWEBŽ«pìž%¤Using the® -n« žoption will proÞduce a prettÿ#yprinÿ"ting lter® ppname« žcompatible to Norman Ramsey'sŽ®ž%¤noÿwÿeb(1)«literate ‹programming Œsystem. ŽThe Œ lter ‹can ‹bÞe ‹inserted inÿ"to Šthe ‹noÿ"wÿ#eb ‹pipÞeline ŒusingŽž%¤noÿ"wÿ#eaÿ#vÿ"e's® m- lter« option.ŽžKHFýeor kexample, nyÿ"ou kcan lbuild ka knoÿ"wÿ#eb lprettÿ#yprinÿ"ting k lter lfor kPÿ"ascal mbÿ"y kissuingŽ®pìžKHpretzel-it -n üpascal þprettÿypascalŽ«žKHinside Sthe® Rlanguages/pascal« êdirectoryýg, Qyÿ"ou'll Qget Ra Pprettÿ#yprinÿ"ting P lter® Qprettÿypascal ä.«ÜThis R l-Žž%¤ter lthen lcan lbÞe lused mwithin® lnoÿwÿeaÿvÿe(1)« ÿbÿ"y ksaÿ#ying:Ž®pìžKHnoÿwÿeaÿvÿe ü- lter prettÿypascal ÿfoo.nÿw° û>® ûfoo.texŽ«žKHThis Ôwill Óprettÿ#yprinÿ"t Òall Òcoßde Ócÿ#hÿ"unks Óusing Óthe ÓPÿ"ascal Ôprettÿ#yprinÿ"ter.>Yýeou Òwill Óneed Ôto Óinclude ÕtheŽ®ž%¤pretzel-noÿwÿeb.stÿy« LaTýfeX qdoÞcumenÿ%t pstÿ#yle qafter qincluding pthe® pnoÿwÿeb.stÿy (« see® rnoÿwÿebstÿyle(1) )Ž«ž%¤to kget lthe loutput ktÿ"ypÞeset ncorrectly nbÿ"y kLaTýfeX.ŽžKHYýeou Ncan Oget Odebugging Ooutput Nfrom Othe Oprettÿ#yprinÿ"ting N lter Pbÿ"y Osetting Qthe Penÿ#vironmenÿ$t Ovÿ"ariableŽ®ž%¤PRETZELžw‰A¯¯ž÷‰NOÿWEBžw‰A¯¯ž÷‰DEBUG« ýto ka knon-nÿ#ull kvÿ"alue, le.g. lin kthe® lbash(1)« ÿshell mbÿ"y ksaÿ#ying:Ž®pìžKHexport þPRETZELžw‰A¯¯ž÷‰NOÿWEBžw‰A¯¯ž÷‰DEBUG=onŽ«žKHDebug output stops only when the vÿ"alue is explicitly unset (in® bash(1)« ­this is the® unset« ¬builtinŽž%¤command.ŽžKHThe ‰noÿ"wÿ#eb ˆoption ‡at ‡presenÿ%t ‡wÿ#orks ˆonly ‡for ‡LaTýfeX ‰as ‰target ‰tÿ"ypÞesetter.÷If ‰the ‰prettÿ#yprinÿ"ter ‰expße-Žž%¤riences Yproblems Xwhen Wprettÿ#yprinÿ"ting Ua Ucertain Wcoßde Ucÿ#hÿ"unk, Tit Tautomatically Vswitcÿ%hes Vto TstandardŽž%¤vÿ"erbatim ™output —of —noÿ"wÿ#eb. ˜Through ˜the ˜inclusion ™of —coßde ˜within ˜rules šof ˜the ™formatted šgrammarŽž%¤ le îit íis îpÞossible ðto íautomate ïindexing. îFýeor ímore ïinformation îsee ðcÿ#hapters ï3 íand í4 íof íthe íPretzel-Žž%¤bÞoÞok, kconÿ#tained lin kthe lPretzel ndistribution.ެžZVCAüjVEAýQTSŽ«pìž%¤The àpretzel-it âshell àscript ácan àonly ßbÞe àrun ßif ßthe àenÿ#vironmenÿ$t ßvÿ"ariables® áPRETZELžw‰A¯¯ž÷‰LIBDIR« sandŽ®ž%¤PRETZELžw‰A¯¯ž÷‰INCLUDE« are xset yto wthe xPretzel zlibrary wdirectory xand vthe wPretzel yinclude xdirectoryýg.Žž%¤During execution, pretzel-it mighÿ#t issue wÿ#arnings that are due to the programs it inÿ"vÿ"okÿ"es (pretzel-Žž%¤it kinÿ"vÿ"okÿ"es® mpretzel(1)«,® t ex(1)«,® pbison(1)« and kthe lGNU lC++ lcompiler).ŽžKHThe® D-n«Ó(noÿ"wÿ#eb) Coption Bwÿ#orks Conly Bfor BLaTýfeX Cas Ctarget Ctÿ"ypÞesetter Eand Ais Bstill Bvÿ"ery Bmÿ#ucÿ#h Aexpßeri-Žž%¤menÿ$tal.ެžZVFILESŽ®pìž%¤/usr/local/lib/pretzel/libpretzel.aŽ«‘Ö‚ž%¤pretzel nrunÿ"time mlibraryýe.Ž®‘þ)~ž%¤/usr/local/lib/pretzel/includeŽ«‘Ö‚ž%¤directory mfor krunÿ"time mlibrary kinclude m les.Ž®‘þ)~ž%¤/usr/local/lib/pretzel/include/pscan.hŽž%¤/usr/local/lib/pretzel/include/pparse.hŽ«‘Ö‚ž%¤template nheaders nfor kthe lgenerated nfunctions.Ž-|Ÿ´®Marcÿ#h k13, k1998‘eJ2ŽŒ‹½«ž´¸pretzel-it(1)‘uppretzel-it(1)Ž®pìžpì/usr/local/lib/pretzel/pretzel-latex.stÿyŽ«‘Ö‚ž%¤LaTýfeX lstÿ#yle lto ktÿ"ypÞeset nPretzel noutput.Ž®‘þ)~ž%¤/usr/local/lib/pretzel/pascal.ftŽž%¤/usr/local/lib/pretzel/pascal.fgŽ«‘Ö‚ž%¤example ninput k les mto kmakÿ#e la kpascal mcompiler.Ž®‘þ)~ž%¤/usr/local/lib/pascalpp«fsexample npascal mprettÿ#yprinÿ"ter lbuilt kwith lPretzel.Ž®ž%¤/usr/local/lib/pretzel/plainpp.oŽ«‘Ö‚ž%¤simpleËmainÉprogramÉlinkÿ"edÉtoÈtheÉprettÿ#yprinÿ"terÉob¼jectÊgener-Žž%¤atedôbÿ"yóPretzel.®`/usr/local/lib/pretzel/noÿwÿebpretzelpp.oŽ«ž%¤mainèprogramètheèinÿ"terfacesëtheèPreztelêprettÿ#yprinÿ"terèwithŽž%¤noÿ"wÿ#eb.ެ‘ý¸’ž4²SEE ËALSOŽ«pìž%¤pretzel(1), nnoÿ"wÿ#eb(1)ޝž%¤The 0Prþhetzelbþkoþhok« 0bÿ"y kFýeelix lGaertner, nincluded min kthe lPretzel ndistribution.Žž%¤The9ÕPretzel9Öhomepage9Öon9Óthe9ÔWWW9Óat®9Óhÿttp://www.iti.informatik.tu-Žž%¤darmstadt.de/~gaertner/pretzelެž4²AÿUTHORŽ«pìž%¤Fýeelix lGaertner, nemail: mfcg@acm.orgŽ‘þŸÄMarcÿ#h k13, k1998‘eJ3ŽŒø—à0áØè iÔóKñ`y@@cmr10óò"V @cmbx10ó!",š@@cmsy10óò"V@@cmbx10óý':@@cmti10ó  b>@@cmmi10ù"<ßßßßßßpretzel-2.0n-2/languages/0000755000000000000000000000000006367034365014035 5ustar rootrootpretzel-2.0n-2/languages/index.list0000644000000000000000000000025006360712747016036 0ustar rootrootthis directory & plain Pretzel input files for several languages cee & simple C cplusplus & simple C++ examples & examples from PretzelBook pascal & pretty good PASCAL pretzel-2.0n-2/languages/examples/0000755000000000000000000000000006360713471015646 5ustar rootrootpretzel-2.0n-2/languages/examples/simpas.ft0000644000000000000000000000054306236070745017501 0ustar rootroot/* simpas.ft -- a simple pretzel example */ %% ";" SEMI "=" | "<" | ">" | "<=" | ">=" | ":=" BINOP "if" IF "then" THEN "else" ELSE "begin" BEG "end" END [0-9]+ NUM [a-zA-Z][a-zA-Z0-9]* ID [\t\ \n] // eat up whitespace pretzel-2.0n-2/languages/examples/simpas.fg0000644000000000000000000000123106255205760017455 0ustar rootroot/* simpas.fg -- a simple pretzel example */ %token SEMI BINOP IF THEN ELSE BEG END NUM ID %% stmt_list : stmt | stmt_list SEMI stmt { $1 $2 force $3 } ; stmt : IF exp THEN stmt { $1 " $" $2 "$ " $3 " " indent $4 outdent } | IF exp THEN stmt ELSE stmt { $1 " $" $2 "$ " $3 indent force $4 outdent force $5 indent force $6 outdent force } | BEG stmt_list END { $1 " " $2 " " $3 } | exp { "$" $1 "$" } ; exp : ID | NUM | exp BINOP exp ; pretzel-2.0n-2/languages/examples/example-frame.tex0000644000000000000000000000032706236074736021123 0ustar rootroot\documentclass{article} \usepackage{pretzel-latex} \begin{document} This is a small example produced by Pretzel and formatted with \LaTeX{}. \begin{ppcode} \input{small-example.tex} \end{ppcode} \end{document} pretzel-2.0n-2/languages/examples/index.list0000644000000000000000000000054206360713464017655 0ustar rootrootthis directory & examples from the PretzelBook Makefile & the Makefile example-frame.tex & a frame for LaTeXing the prettyprinted code simpas.fg & Pretzel formatted grammar simpas.ft & Pretzel formatted tokens small-example.simpas & a small example to be prettyprinted small-example.tex & results from running the prettyprinter on small-example.simpas pretzel-2.0n-2/languages/examples/small-example.simpas0000644000000000000000000000007006236401666021624 0ustar rootrootif a=1 then b:=1; if a<=1 then begin b:=2 end else b:=a pretzel-2.0n-2/languages/examples/index.html0000644000000000000000000000235306360713471017646 0ustar rootroot Index file for directory "pretzel/languages/examples" of Pretzel distribution

Index file for directory "pretzel/languages/examples" of Pretzel distribution

Files and directories are:

this directory

    examples from the PretzelBook
Makefile
    the Makefile
example-frame.tex
    a frame for LaTeXing the prettyprinted code
simpas.fg
    Pretzel formatted grammar
simpas.ft
    Pretzel formatted tokens
small-example.simpas
    a small example to be prettyprinted
small-example.tex
    results from running the prettyprinter on small-example.simpas

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:50:50 MESZ 1997 pretzel-2.0n-2/languages/examples/small-example.tex0000644000000000000000000000035306255207123021125 0ustar rootrootif $a=1$ then \pretzelindent{}$b:=1$\pretzeloutdent{};\pretzelforce{}if $a<=1$ then\pretzelindent{}\pretzelforce{}begin $b:=2$ end\pretzeloutdent{}\pretzelforce{}else\pretzelindent{}\pretzelforce{}$b:=a$\pretzeloutdent{}\pretzelforce{}pretzel-2.0n-2/languages/examples/Makefile0000644000000000000000000000100606255452752017310 0ustar rootroot# $Id: Makefile,v 1.1 1996/12/17 08:12:26 gaertner Exp $ #---------------------------------------------------------------------- # # Makefile for directory languages/examples (small examples of pretzel) # also featured in the Pretzelbook # example: simpaspp simpaspp < small-example.simpas > small-example.tex latex example-frame.tex simpaspp: simpas.fg simpas.ft pretzel-it simpas simpaspp clean: rm -f example-frame.aux example-frame.dvi example-frame.log \ ptokdefs.h simpas.lex.c simpas.tab.c simpaspp pretzel-2.0n-2/languages/index.html0000644000000000000000000000163606360712757016041 0ustar rootroot Index file for directory "pretzel/languages" of Pretzel distribution

Index file for directory "pretzel/languages" of Pretzel distribution

Files and directories are:

this directory

    plain Pretzel input files for several languages
cee
    simple C
cplusplus
    simple C++
examples
    examples from PretzelBook
pascal
    pretty good PASCAL

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:45:20 MESZ 1997 pretzel-2.0n-2/languages/pascal/0000755000000000000000000000000010765026553015275 5ustar rootrootpretzel-2.0n-2/languages/pascal/pretzel-it-bootstrap0000755000000000000000000002411006651062114021323 0ustar rootroot#!/bin/sh # $Id: pretzel-it,v 2.2 1998/12/03 10:58:39 felix Exp $ #---------------------------------------------------------------------- # # pretzel-it-bootstrap --- bootstrapping version of pretzel-it # # DO NOT USE! DO NOT USE! DO NOT USE! DO NOT USE! DO NOT USE! DO NOT USE! # # based on version 2.2 of pretzel-it. Changes are: predefined # locations of PRETZEL_LIBDIR and PRETZEL_INCLUDE and hardcoded # invokation of ../../pretzel instead of expecting to find pretzel # in PATH. See Makefile of languages/pascal for more expanations. # SYNOPSIS # # pretzel-it [-iqvdnh] language ppname # # # pretzel-it tries to produce a prettyprinter from the input files # `language.ft' and `language.fg'. The prettyprinter is encapsulated in # a minimal main program called `ppname'. It's usgage then is: # # ppname tex-code # # pretzel-it will leave the C code of the prettyprinter in the current # directory. If the -i option is given, all intermediate files, such # as the flex and Bison files, as well as the object code of the C # files are left there too. # # Filenames of the C code are: language.lex.c, language.tab.c and # ptokdefs.h for the token header. # # pretzel-it expects to find the `pretzel' program in your PATH. Also # it looks for the pretzel library and include files in the directories # specified by the environment variables PRETZEL_LIBDIR and PRETZEL_INCLUDE. # # # OPTIONS # # -i don't remove intermediate products (flex/Bison source # and prettyprinter object code) # -q run quietly # -v verbose, print commands before invoking (for debugging) # -d turn prettyprinter debugging features on by default, # produce an .output file for detailed diagnosis of parser # (for debugging the prettyprinting grammar) # -h print help message # # -n noweb option: instead of producing a standalone # prettyprinter `ppname' it will produce a noweb # prettyprinting filter `ppname' that can be used as # additional filter with noweb's -filter option # (and LaTeX as typesetter). Without the -i option # it will remove _all_ intermediates and leave only the # filter in the current directory. # # # CAVEATS: # # pretzel-it is very simple and will only produce default # prettyprinters. Use the specialized Makefile if you want to do # special things like using several prettyprinters within one # program. # # The noweb option is new and very experimental. # # # IMPLEMENTATION NOTES # # After checking the arguments, the commands that are used to # invoke flex, Bison and the compiler are pieced together and then # executed. # # The noweb option builds a normal prettyprinter but links it with # a different main function and removes all intermediates. # cmd=`basename $0` usage() { echo "usage: $cmd [-inqvdh] language ppname" >&2 echo "use -h option for full usage" >&2 exit 1 } full_usage() { echo "usage: $cmd [-inqvdh] language ppname" >&2 echo "options: " >&2 echo " -i don't remove intermediate products" >&2 echo " -q run quietly" >&2 echo " -v verbose, print commands before invoking" >&2 echo " -d turn prettyprinter debugging features on" >&2 echo " -h print this help message" >&2 echo " -n (experimental) noweb option" >&2 exit 0 } envnote() { echo "you need to set the environment variables" >&2 echo "PRETZEL_LIBDIR and PRETZEL_INCLUDE to the" >&2 echo "pretzel library and include directories." >&2 exit 1 } # normalize and check arguments: cleanup_intermediates=true run_noisy=true verbose_mode='' build_debug_pp='' noweb_mode='' while getopts 'iqvdnh' option do case "$option" in i) cleanup_intermediates='' ;; q) run_noisy='' ;; v) verbose_mode=true ;; d) build_debug_pp=true ;; n) noweb_mode=true ;; h) full_usage ;; # add more options here *) usage ;; esac done # number of remaining arguments has to be 2: shift `expr $OPTIND - 1` test $# -eq 2 || usage # check if environment variables have been set #test $PRETZEL_LIBDIR || export PRETZEL_LIBDIR=/usr/lib/pretzel # envnote #test $PRETZEL_INCLUDE || export PRETZEL_INCLUDE=/usr/include/pretzel # envnote # hardcoded for bootstrapping: PRETZEL_LIBDIR=../../ PRETZEL_INCLUDE=../../include # ----------------------------------------------------------------- # Build commands that are invoked by the script: # hardcoded for bootstrapping: pretzel_command="../../bin/pretzel -q $1" bison_command="bison -d $1.y -o $1.tab.c" # -v flag produces the .output file for detailed diagnosis debug_bison_command="bison -v -d $1.y -o $1.tab.c" after_bison="mv $1.tab.h ptokdefs.h" flex_command="flex -t $1.l > $1.lex.c" # don't need link commands on command line compile_flex="g++ -c -I$PRETZEL_INCLUDE -g $1.lex.c" compile_bison="g++ -c -I$PRETZEL_INCLUDE -g $1.tab.c" # note that the order of the arguments is important for portability link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/plainpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # this is used if you're building a prettyprinter for debugging debug_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/plaindpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # cleanup_command="rm -f $1.l $1.y $1.lex.o $1.tab.o" # special noweb command (invoked instead of the normal link commands): noweb_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/nowebpretzelpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" # currently the same as noweb_link_command: noweb_debug_link_command="g++ $1.lex.o $1.tab.o $PRETZEL_LIBDIR/nowebpretzelpp.o \ -I$PRETZEL_INCLUDE -L$PRETZEL_LIBDIR -lpretzel -g -o $2" noweb_cleanup_command="rm -f $1.l $1.y $1.lex.o $1.tab.o $1.lex.c \ $1.tab.c ptokdefs.h" # ------------------------------------------------------------------ # now go to work: let's run the different programs on the files one # at a time and be sure to bail out when one of them returns with an # error. # now go to work: run pretzel on the input files. if [ "$run_noisy" ] then echo "starting to pretzel..." fi if [ "$verbose_mode" ] then echo $pretzel_command fi eval $pretzel_command || exit 1 # now run flex and Bison on them and try to compile... if [ "$run_noisy" ] then echo "preprocessing..." fi if [ "$verbose_mode" ] then echo $bison_command fi if [ "$build_debug_pp" ] then eval $debug_bison_command || exit 1 else eval $bison_command || exit 1 fi eval $after_bison if [ "$verbose_mode" ] then echo $flex_command fi eval $flex_command || exit 1 if [ "$run_noisy" ] then echo "processing .ft file..." fi if [ "$verbose_mode" ] then echo $compile_flex fi eval $compile_flex || exit 1 if [ "$run_noisy" ] then echo "processing .fg file..." fi if [ "$verbose_mode" ] then echo $compile_bison fi eval $compile_bison || exit 1 if [ "$build_debug_pp" ] then if [ "$noweb_mode" ] then # case 1: debug and noweb if [ "$run_noisy" ] then echo "building noweb filter $2 (turning debug features on)..." fi if [ "$verbose_mode" ] then echo $noweb_debug_link_command fi eval $noweb_debug_link_command || exit 1 else # case 2: debug and not noweb if [ "$run_noisy" ] then echo "building prettyprinter $2 (turning debug features on)..." fi if [ "$verbose_mode" ] then echo $debug_link_command fi eval $debug_link_command || exit 1 fi else if [ "$noweb_mode" ] then # case 3: normal noweb if [ "$run_noisy" ] then echo "building noweb filter $2..." fi if [ "$verbose_mode" ] then echo $noweb_link_command fi eval $noweb_link_command || exit 1 else # case 4: normal if [ "$run_noisy" ] then echo "building prettyprinter $2..." fi if [ "$verbose_mode" ] then echo $link_command fi eval $link_command || exit 1 fi fi # if [ "$cleanup_intermediates" ] then if [ "$noweb_mode" ] then if [ "$run_noisy" ] then echo "cleaning up and leaving only noweb filter..." fi if [ "$verbose_mode" ] then echo $noweb_cleanup_command fi eval $noweb_cleanup_command else # cleanup but not in noweb mode if [ "$run_noisy" ] then echo "cleaning up..." fi if [ "$verbose_mode" ] then echo $cleanup_command fi eval $cleanup_command fi fi if [ "$run_noisy" ] then echo "done." fi #====================================================================== # # $Log: pretzel-it,v $ # Revision 2.2 1998/12/03 10:58:39 felix # can use standard search paths for PRETZEL_XXX if variables are # not set (thanks to I think Dave Wilson). # # Revision 2.1 1998/04/25 08:03:09 gaertner # produces .output file from bison when -d option is given for # detailed grammar diagnosis in the presence of conflicts. # # Revision 2.0 1996/12/16 17:35:52 gaertner # release 2.0 # # Revision 1.10 1996/11/14 18:13:23 gaertner # noweb option should work now. Changes the text lines that are # printed out to the screen because they show too many internals. # # Revision 1.9 1996/11/14 18:03:13 gaertner # Added noweb option. Added -h option. # # Revision 1.8 1996/09/17 13:46:37 gaertner # Changed CC to g++ in compiler lines. Also added the `cleanup' option. # # Revision 1.7 1996/03/22 10:10:11 gaertner # added -d option for grammar debugging. # # Revision 1.6 1996/03/21 11:08:29 gaertner # Corrected argument checking and enhanced documentation. # # Revision 1.5 1996/02/06 19:24:59 gaertner # Added new options -i -q -v. Bails out when an error is encountered. # Invoked commands are configured in one place to ease maintenance. # # Revision 1.4 1996/02/06 17:28:07 gaertner # Version before re-writing the tool. # # Revision 1.3 1995/08/30 17:51:57 gaertner # tex->lex in rm-line. # # Revision 1.2 1995/08/30 17:48:41 gaertner # Moved link objects to the front of the compiler line. Some # compilers need this. # # Revision 1.1 1995/08/30 17:45:49 gaertner # Initial revision # # pretzel-2.0n-2/languages/pascal/nice.pas0000644000000000000000000000014405445307452016716 0ustar rootroot if (a<> b) then begin i:=i+1;;; i+1 end; i:=0; repeat a:=a; abcdef; until (a=true); i=0; pretzel-2.0n-2/languages/pascal/pascal.ft0000644000000000000000000000477706021122311017065 0ustar rootroot/* this is an example formatted token file for a pascal * prettyprinter. */ %% "<>" MATH { "$\\neq$" } // not equal sign "<=" MATH { "$\\leq$" } // less or equal ">=" MATH { "$\\geq$" } // greater or equal ":=" MATH { "\\hbox{${}\\mathrel{:=}{}$}" } // assignment '([^']|'')*' SIMP { "{\\tt " + ** + "}" } // strings "(" OPEN ")" CLOSE "[" OPEN "]" CLOSE "*" MATH { "$\\ast$" } "," MATH { ** + opt9 } ".." MATH "." SIMP ":" COLON ";" SEMI "=" MATH "+" MATH "-" MATH "<" MATH { "$<$" } ">" MATH { "$>$" } "/" MATH // this to allow underscores in identifiers: "_"[a-zA-Z0-9]* ID_TYPE {"\\" + ** } [0-9]+ SIMP [0-9]*"."[0-9]+ SIMP and MATH {"{\\bf and}"} array ALPHA {"{\\bf array}"} begin BEG {force + "\n" + "{\\bf begin}" } boolean SIMP {"{\\bf boolean}"} case CASE {force + "{\\bf case}" + cancel } const INTRO {force + backup + "{\bf const}"} div MATH {" {\\bf div} "} do OMEGA {"{\\bf do}"} downto MATH {"{\\bf downto}"} else ELSE {"{\\bf else}" } end END {"{\\bf end}" } for ALPHA {"{\\bf for}" } function PROC {big_force + backup + "{\\bf function} " } if ALPHA {"{\\bf if}" } integer SIMP {"{\\bf integer}"} mod MATH {"{\\bf mod}"} not MATH {"{\\bf not}"} of OMEGA {"{\\bf of} " + cancel } or MATH {"{\\bf or} "} procedure PROC {big_force + backup + "{\\bf procedure} " } program PROC {big_force + backup + "{\\bf program} "} readln SIMP {"{\\bf readln}"} real SIMP {"{\\bf real}"} record RECORD {"{\\bf record}"} repeat BEG {force + "{\\bf repeat}" } then OMEGA {"{\\bf then}" } to MATH {" {\\bf to} "} type INTRO {force + backup + "{\\bf type}" } until UNTIL {force + "{\\bf until}" } var INTRO {force + backup + "{\\bf var} " } while ALPHA {force + "{\\bf while}" } with ALPHA {force + "{\\bf with}"} write SIMP {"{\\bf write}"} writeln SIMP {"{\\bf writeln}"} "{"[^}]*"}" COMMENT { "\\hbox{$\\{${" + ** + "}$\\}$}" } // comments [a-zA-Z][a-zA-Z0-9]* ID_TYPE // identifiers [\t\ \n] // eat up whitespace . // eat up other non matching characters pretzel-2.0n-2/languages/pascal/frame.dvi0000644000000000000000000000155006520322640017062 0ustar rootroot÷ƒ’À;è TeX output 1998.04.25:1057‹ÿÿÿÿ l ý» ' ýü¤ ‘?ó#ò"V cmbx10Îfunction‘UUó!ý': cmti10ÌWurzelóKñ`y cmr10²(Ìx²:Îreal²):Îreal²;ŽŸ‘?Îv‘ÿ\rar‘UUÌx0²,Ìx1²:Îreal²;Ž¡‘LUVÎbQÇeginŽ¡‘Sif–UUÌxó !",š cmsy10¸²0“ÎthenŽ¡‘`UXbQÇeginŽ¡‘gÌx1‘Dz:=ŽŽ‘kÌx²;Ž¡‘gÎrepQÇeatŽ¡‘qÌx0‘Dz:=ŽŽ‘kÌx1²;Ž¡‘qÌx1‘Dz:=ŽŽ‘k(Ìx0²+Ìx²/Ìx0²)/2;Ž¡‘gÎun®9til‘UU²(Ìx0²+Ìabs²(Ìx0²-Ìx1²)=Ìx0²);Ž¡‘gÌWurzel‘Dz:=ŽŽ‘kÌx1²;Ž¡‘]ÎendŽ¡‘SelseŽ¡‘`UXbQÇeginŽ¡‘gwriteln²(ó$ßê #include"attr.h" #include"output.h" class Pparse { public: Pparse() {}; ~Pparse() {}; virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*) = 0; }; // actual prettyprinter: #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; \end{verbatim} % We'll create an instance of this class and read input from as many files as specified at the command line. @ Here's an overview over the implementation. <<*>>= /* implementation of a tester for a prettyprinter */ <

> <> @ \subsection{Details} We'll use a standard prettyprinter and output ASCII text to [[stdout]]. <
>= #include #include "Ppparse.h" #include "asciioutput.h" @ Here's the main program. It's a loop over all the names on the command line. Remember that [[argc]] is always one larger than the number of elements on the command line. So we exit the loop when [[filecount]] reaches the value of [[argc]]. <>= int main( int argc, char *argv[] ) { <> char* filename; int filecount = 1; while (filecount < argc) { filename = argv[filecount]; <> filecount++; } return(0); } @ <>= if (argc <= 1) { cerr << argv[0] << ": error -- missing file name(s)." << endl << "Specify one or more files to be prettyprinted to stdout." << endl; exit(1); } @ Here's where the work is done. <>= { Ppparse prettyprinter; Ascii_terminal_output outp(cout); cout << endl << "** Processing file " << filename << endl; ifstream infile; /* file to read from */ infile.open(filename); assert(infile!=NULL); prettyprinter.prettyprint(&infile, &cout); } @ <
>= #include #include #include @ \end{document} % % $Log: multiple.nw,v $ % Revision 2.0 1996/12/17 07:56:41 gaertner % *** empty log message *** % % % pretzel-2.0n-2/languages/pascal/index.list0000644000000000000000000000112106360713762017275 0ustar rootrootthis directory & the first Pretzel input: a prettyprinter for PASCAL Makefile & example Makefile for making a pretzel prettyprinter (targets see README) README & more information pascal.fg & formatted grammar file for pascal pascal.ft & formatted tokens file for pascal wurzel.pas & a few pascal examples gauss.pas & ml.pas & nice.pas & pprinted.tex & TeX code output by the pretzel prettyprinter frame.tex & A TeX file that can be used as a frame for the prettyprinted text (it includes pprinted.tex) multiple.nw & A program to test multiple prettyprinters in a single source (is rather old) pretzel-2.0n-2/languages/pascal/README0000644000000000000000000000230506255450736016160 0ustar rootroot $Id: README,v 2.0 1996/12/17 07:55:09 gaertner Exp $ A few hints to the files in this directory: ------------------------------------------- Makefile example Makefile for making a pretzel prettyprinter (targets see below) pascal.fg formatted grammar file for pascal pascal.ft formatted tokens file for pascal [plainpp.c] [Main program that uses the prettyprinter (reads stdin and writes to stdout).] -> moved to ../../main wurzel.pas a few pascal examples gauss.pas ml.pas nice.pas pprinted.tex TeX code output by the pretzel prettyprinter frame.tex A TeX file that can be used as a frame for the prettyprinted text (it includes pprinted.tex) multiple.nw A program to test multiple prettyprinters in a single source (is rather old) Makefile targets: ----------------- test Make a prettyprinter for default language using pretzel-it and test it. complextest Make a prettyprinter using explicit rules of the Makefile and test it. The default language and the prettyprinted example may be configured in the Makefile. $Log: README,v $ Revision 2.0 1996/12/17 07:55:09 gaertner *** empty log message *** Revision 1.1 1995/09/05 14:50:14 gaertner Initial revision pretzel-2.0n-2/languages/pascal/gauss.pas0000644000000000000000000000477605445333002017127 0ustar rootroot{1:}PROGRAM GAUSS(INPUT,OUTPUT);CONST CHOOSE=3;NMAX=10;ITISATEST=TRUE; TYPE LES=RECORD N:1..NMAX;A:ARRAY[1..NMAX,1..NMAX]OF REAL; X:ARRAY[1..NMAX]OF REAL;B:ARRAY[1..NMAX]OF REAL;END;VAR Q:LES; ERR:BOOLEAN;{:1}{2:}PROCEDURE PRINTTHEMATR(Q:LES);VAR I,J:INTEGER; BEGIN FOR I:=1 TO Q.N DO BEGIN WRITE('| '); FOR J:=1 TO Q.N DO BEGIN WRITE(Q.A[I,J]:5:2,' ');END; WRITE('| | x',I:2,' | '); IF I=(Q.N DIV 2)THEN WRITE('= ')ELSE WRITE(' '); WRITELN('| ',Q.B[I]:5:2,' |');END;WRITELN;END;{:2}{3:} PROCEDURE READTHEINPUT(X:INTEGER;VAR Q:LES); BEGIN CASE X OF 1:BEGIN WITH Q DO BEGIN N:=5;A[1,1]:=2;A[1,2]:=-3; A[1,3]:=1;A[1,4]:=1;A[1,5]:=-1;A[2,1]:=-1;A[2,2]:=-1;A[2,3]:=1; A[2,4]:=5;A[2,5]:=-1;A[3,1]:=3;A[3,2]:=7;A[3,3]:=-9;A[3,4]:=1;A[3,5]:=5; A[4,1]:=-2;A[4,2]:=3;A[4,3]:=1;A[4,4]:=-1;A[4,5]:=2;A[5,1]:=1;A[5,2]:=1; A[5,3]:=-3;A[5,4]:=1;A[5,5]:=1;B[1]:=-2;B[2]:=15;B[3]:=19;B[4]:=13; B[5]:=3;END;END;2:BEGIN WITH Q DO BEGIN N:=5;A[1,1]:=1;A[1,2]:=5; A[1,3]:=3;A[1,4]:=-5;A[1,5]:=1;A[2,1]:=-2;A[2,2]:=-9;A[2,3]:=-13; A[2,4]:=11;A[2,5]:=2;A[3,1]:=1;A[3,2]:=7;A[3,3]:=-11;A[3,4]:=8; A[3,5]:=12;A[4,1]:=-1;A[4,2]:=-4;A[4,3]:=-8;A[4,4]:=10;A[4,5]:=10; A[5,1]:=2;A[5,2]:=9;A[5,3]:=14;A[5,4]:=-9;A[5,5]:=-1;B[1]:=11;B[2]:=-5; B[3]:=74;B[4]:=57;B[5]:=21;END;END;3:BEGIN WITH Q DO BEGIN N:=5; A[1,1]:=2520;A[1,2]:=1260;A[1,3]:=840;A[1,4]:=630;A[1,5]:=504; A[2,1]:=1260;A[2,2]:=840;A[2,3]:=630;A[2,4]:=504;A[2,5]:=420; A[3,1]:=840;A[3,2]:=630;A[3,3]:=504;A[3,4]:=420;A[3,5]:=360;A[4,1]:=630; A[4,2]:=504;A[4,3]:=420;A[4,4]:=360;A[4,5]:=315;A[5,1]:=504;A[5,2]:=420; A[5,3]:=360;A[5,4]:=315;A[5,5]:=280;B[1]:=5754;B[2]:=3654;B[3]:=2754; B[4]:=2229;B[5]:=1879;END;END;END;IF ITISATEST THEN PRINTTHEMATR(Q);END; {:3}{4:}PROCEDURE COMPUTETHESO(VAR Q:LES);VAR K,L,C,I:INTEGER; SUM,F:REAL;BEGIN{5:}FOR K:=1 TO Q.N DO BEGIN{6:}L:=K+1; WHILE(L<=Q.N)AND NOT ERR DO BEGIN IF Q.A[K,K]<>0 THEN BEGIN WITH Q DO F :=A[L,K]/A[K,K];{7:} FOR C:=K TO Q.N DO BEGIN WITH Q DO A[L,C]:=A[L,C]-(F*A[K,C]);END;{:7}; WITH Q DO B[L]:=B[L]-(F*B[K])END ELSE BEGIN ERR:=TRUE;END;L:=L+1;END; {:6};IF ITISATEST THEN PRINTTHEMATR(Q);END;{:5}; IF NOT ERR THEN BEGIN{8:}FOR L:=Q.N DOWNTO 1 DO BEGIN I:=L+1;SUM:=0; WHILE I<=Q.N DO BEGIN SUM:=SUM+Q.A[L,I]*Q.X[I];I:=I+1;END; Q.X[L]:=(Q.B[L]-SUM)/Q.A[L,L];END;{:8};END;END;{:4}{9:} PROCEDURE SHOWTHESOLUT(Q:LES);VAR L:INTEGER; BEGIN FOR L:=1 TO Q.N DO BEGIN WRITELN('is this right? x',L,' : ',Q.X[L] );END;END;{:9}{10:}BEGIN ERR:=FALSE;READTHEINPUT(CHOOSE,Q); COMPUTETHESO(Q); IF NOT ERR THEN SHOWTHESOLUT(Q)ELSE WRITELN('There has been an error!'); END.{:10} pretzel-2.0n-2/languages/pascal/index.html0000644000000000000000000000311306360713770017270 0ustar rootroot Index file for directory "pretzel/languages/pascal" of Pretzel distribution

Index file for directory "pretzel/languages/pascal" of Pretzel distribution

Files and directories are:

this directory

    the first Pretzel input: a prettyprinter for PASCAL
Makefile
    example Makefile for making a pretzel prettyprinter (targets see README)
README
    more information
pascal.fg
    formatted grammar file for pascal
pascal.ft
    formatted tokens file for pascal
wurzel.pas
    a few pascal examples
gauss.pas
ml.pas
nice.pas
pprinted.tex
    TeX code output by the pretzel prettyprinter
frame.tex
    A TeX file that can be used as a frame for the prettyprinted text (it includes pprinted.tex)
multiple.nw
    A program to test multiple prettyprinters in a single source (is rather old)

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:54:00 MESZ 1997 pretzel-2.0n-2/languages/pascal/frame.log0000644000000000000000000001672006520322640017066 0ustar rootrootThis is TeX, Version 3.14159 (C version 6.1) (format=latex 96.11.20) 25 APR 1998 10:57 **frame.tex (frame.tex LaTeX2e <1996/06/01> Hyphenation patterns for english, german, loaded. (/usr/local/lib/texmf/tex/latex/base/latex209.def File: latex209.def 1995/07/07 v0.47 Standard LaTeX file Entering LaTeX 2.09 compatibility mode. \footheight=\dimen102 \@maxsep=\dimen103 \@dblmaxsep=\dimen104 (/usr/local/lib/texmf/tex/latex/base/tracefnt.sty Package: tracefnt 1995/06/15 v3.0b Standard LaTeX package (font tracing) \tracingfonts=\count79 LaTeX Info: Redefining \selectfont on input line 133. ) \symbold=\mathgroup4 \symsans=\mathgroup5 \symtypewriter=\mathgroup6 \symitalic=\mathgroup7 \symsmallcaps=\mathgroup8 \symslanted=\mathgroup9 LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 276. LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 277. LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 278. LaTeX Font Info: Redeclaring math alphabet \mathit on input line 284. LaTeX Info: Redefining \em on input line 294. (/usr/local/lib/texmf/tex/latex/base/latexsym.sty Package: latexsym 1995/03/18 v2.2a Standard LaTeX package (lasy symbols) \symlasy=\mathgroup10 LaTeX Font Info: Overwriting symbol font `lasy' in version `bold' (Font) U/lasy/m/n --> U/lasy/b/n on input line 81. ) LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 359. LaTeX Font Info: Redeclaring math delimiter \rgroup on input line 361. LaTeX Font Info: Redeclaring math delimiter \bracevert on input line 363. (/usr/local/lib/texmf/tex/latex/config/latex209.cfg (/usr/local/lib/texmf/tex/latex/base/oldlfont.sty Package: oldlfont 1994/11/06 v2.2j Standard LaTeX package LaTeX Font Info: Redeclaring symbol font `bold' on input line 97. LaTeX Font Info: Overwriting symbol font `bold' in version `normal' (Font) OT1/cmr/bx/n --> OT1/cmr/bx/n on input line 97. LaTeX Font Info: Overwriting symbol font `bold' in version `bold' (Font) OT1/cmr/bx/n --> OT1/cmr/bx/n on input line 97. LaTeX Font Info: Redeclaring symbol font `sans' on input line 98. LaTeX Font Info: Overwriting symbol font `sans' in version `normal' (Font) OT1/cmss/m/n --> OT1/cmss/m/n on input line 98. LaTeX Font Info: Overwriting symbol font `sans' in version `bold' (Font) OT1/cmss/m/n --> OT1/cmss/m/n on input line 98. LaTeX Font Info: Redeclaring symbol font `typewriter' on input line 99. LaTeX Font Info: Overwriting symbol font `typewriter' in version `normal' (Font) OT1/cmtt/m/n --> OT1/cmtt/m/n on input line 99. LaTeX Font Info: Overwriting symbol font `typewriter' in version `bold' (Font) OT1/cmtt/m/n --> OT1/cmtt/m/n on input line 99. LaTeX Font Info: Redeclaring symbol font `italic' on input line 100. LaTeX Font Info: Overwriting symbol font `italic' in version `normal' (Font) OT1/cmr/m/it --> OT1/cmr/m/it on input line 100. LaTeX Font Info: Overwriting symbol font `italic' in version `bold' (Font) OT1/cmr/m/it --> OT1/cmr/m/it on input line 100. LaTeX Font Info: Redeclaring symbol font `smallcaps' on input line 101. LaTeX Font Info: Overwriting symbol font `smallcaps' in version `normal' (Font) OT1/cmr/m/sc --> OT1/cmr/m/sc on input line 101. LaTeX Font Info: Overwriting symbol font `smallcaps' in version `bold' (Font) OT1/cmr/m/sc --> OT1/cmr/m/sc on input line 101. LaTeX Font Info: Redeclaring symbol font `slanted' on input line 102. LaTeX Font Info: Overwriting symbol font `slanted' in version `normal' (Font) OT1/cmr/m/sl --> OT1/cmr/m/sl on input line 102. LaTeX Font Info: Overwriting symbol font `slanted' in version `bold' (Font) OT1/cmr/m/sl --> OT1/cmr/m/sl on input line 102. LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 103. LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 104. LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 105. LaTeX Font Info: Redeclaring math alphabet \mathsc on input line 106. LaTeX Font Info: Redeclaring math alphabet \mathsl on input line 107. LaTeX Font Info: Redeclaring math alphabet \mathit on input line 111. LaTeX Font Info: Redeclaring math alphabet \mit on input line 112. LaTeX Font Info: Redeclaring math alphabet \cal on input line 113. LaTeX Info: Redefining \rm on input line 114. LaTeX Info: Redefining \sf on input line 115. LaTeX Info: Redefining \sl on input line 116. LaTeX Info: Redefining \bf on input line 117. LaTeX Info: Redefining \sc on input line 118. LaTeX Info: Redefining \it on input line 119. LaTeX Info: Redefining \tt on input line 120. LaTeX Info: Redefining \em on input line 121. ) (/usr/local/lib/texmf/tex/latex/tools/rawfonts.sty Package: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility (/usr/local/lib/texmf/tex/latex/tools/somedefs.sty Package: somedefs 1994/06/01 Toolkit for optional definitions ) LaTeX Font Info: Try loading font information for U+lasy on input line 30. (/usr/local/lib/texmf/tex/latex/base/Ulasy.fd File: Ulasy.fd 1995/03/18 v2.2aLaTeX symbol font definitions )))) (/usr/local/lib/texmf/tex/latex/base/article.cls Document Class: article 1995/06/26 v1.3g Standard LaTeX document class (/usr/local/lib/texmf/tex/latex/base/size10.clo File: size10.clo 1995/06/19 v1.3e Standard LaTeX file (size option) ) \c@part=\count80 \c@section=\count81 \c@subsection=\count82 \c@subsubsection=\count83 \c@paragraph=\count84 \c@subparagraph=\count85 \c@figure=\count86 \c@table=\count87 \abovecaptionskip=\skip41 \belowcaptionskip=\skip42 Compatibility mode: definition of \rm ignored. Compatibility mode: definition of \sf ignored. Compatibility mode: definition of \tt ignored. Compatibility mode: definition of \bf ignored. Compatibility mode: definition of \it ignored. Compatibility mode: definition of \sl ignored. Compatibility mode: definition of \sc ignored. LaTeX Info: Redefining \cal on input line 489. LaTeX Info: Redefining \mit on input line 490. \bibindent=\dimen105 ) (/users/gaertner/tex/inputs/pretzel-latex.sty \ind=\count88 ) No file frame.aux. LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 6. LaTeX Font Info: ... okay on input line 6. LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 6. LaTeX Font Info: ... okay on input line 6. LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 6. LaTeX Font Info: ... okay on input line 6. LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 6. LaTeX Font Info: ... okay on input line 6. LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 6. LaTeX Font Info: ... okay on input line 6. LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 6. LaTeX Font Info: ... okay on input line 6. (pprinted.tex LaTeX Font Info: External font `cmex10' loaded for size (Font) <7> on input line 2. LaTeX Font Info: External font `cmex10' loaded for size (Font) <5> on input line 2. ) [1 ] (frame.aux) ) Here is how much of TeX's memory you used: 557 strings out of 10910 5710 string characters out of 72200 47696 words of memory out of 262141 3421 multiletter control sequences out of 9500 22498 words of font info for 84 fonts, out of 150000 for 255 14 hyphenation exceptions out of 607 27i,4n,22p,580b,150s stack positions out of 300i,40n,60p,3000b,4000s Output written on frame.dvi (1 page, 872 bytes). pretzel-2.0n-2/languages/pascal/frame.aux0000644000000000000000000000001006520322637017071 0ustar rootroot\relax pretzel-2.0n-2/languages/pascal/wurzel.pas0000644000000000000000000000056605655245002017333 0ustar rootroot function Wurzel ( x : real ) : real; var x0, x1 : real; begin if x>=0 then begin x1:=x; repeat x0:=x1; x1:=(x0+x/x0)/2; until (x0 + abs(x0-x1) = x0); Wurzel:=x1; end else begin writeln('Fehler: Wurzel ist komplex!'); end; end; { Wurzel } pretzel-2.0n-2/languages/pascal/Makefile0000644000000000000000000001171406651063071016734 0ustar rootroot# $Id: Makefile,v 2.2 1999/01/19 11:01:18 felix Exp $ # # Makefile for a pretzel prettyprinter # # prefix of format files. Will produce pp executable. LANG = pascal # the prettyprinter main() function PROG = $(LANG)pp # name of file to be prettyprinted LANGEX = wurzel.pas # name of the token definition file for the scanner TOKDEFS = ptokdefs.h # where's pretzel-it? PRETZELIT = ../../pretzel-it/pretzel-it # which compiler are we using? CC = g++ # compiler options: OPT = -I../../include -L../.. -lpretzel -g # suffix of formatted token files (without dot) FT = ft # suffix of formatted grammar files (without dot) FG = fg # sources: PSRCS = $(LANG).l $(LANG).y # corresponding C sources PCSRCS = $(LANG).lex.c $(LANG).tab.c # objects that the prettyprinter needs created: POBJS = $(LANG).lex.o $(LANG).tab.o # global main() object (made in main/ of Pretzel distribution) MAINOBJ = ../../plainpp.o # headers? HEADERS = $(TOKDEFS) # # RM = rm -f LEX = flex YACC = bison XDVI = dvix11 .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h .$(FT) .$(FG) .ft.l: pretzel -t $* .fg.y: pretzel -g $* .y.c: $(YACC) $*.y .l.c: $(LEX) -t $*.l > $*.lex.c .c.o: $(CC) -c $(OPT) $*.c .nw.c: notangle <$*.nw >$*.c $(PROG): $(HEADERS) $(POBJS) $(CC) $(OPT) -o $(LANG)pp $(POBJS) $(MAINOBJ) $(POBJS): $(PCSRCS) $(PCSRCS): $(PSRCS) $(TOKDEFS): $(LANG).y $(YACC) -d $(LANG).y mv $(LANG).tab.h $(TOKDEFS) $(LANG).tab.c: $(LANG).y $(YACC) $(LANG).y $(LANG).lex.c: $(LANG).l $(LEX) -t $(LANG).l > $(LANG).lex.c # test is always a simple test test: simpletest # test pretzel using pretzel-it: simpletest: $(PRETZELIT) $(LANG) $(LANG)pp $(LANG)pp < $(LANGEX) > pprinted.tex latex frame.tex $(XDVI) frame.dvi # test the generated prettyprinter using the makefile: complextest: $(PROG) $(PROG) < $(LANGEX) > pprinted.tex latex frame.tex $(XDVI) frame.dvi # can't use pretzel-it here because this is a bootstrapping # target. Use a special copy of pretzel-it here at bootstrap # time. (Don't add ../../bin to PATH because this is shell # specific) # # If Pretzel is already installed, the line should look like # this: # # $(PRETZEL-IT) $(LANG) $(LANGPP) # pretzeledpascalpp: ./pretzel-it-bootstrap $(LANG) $(LANG)pp # $(PRETZEL-IT) $(LANG) $(LANGPP) # MULTOBJS = multiple.o $(LANG).lex.o $(LANG).tab.o multiple: $(MULTOBJS) $(CC) $(OPT) -o multiple $(MULTOBJS) multiple.o: multiple.c multiple.c: multiple.nw # remove all intermediate products clean: $(RM) $(HEADERS) $(POBJS) $(PCSRCS) $(PSRCS) # remove all final products clobber: clean $(RM) $(LANG)pp # make a neat little bundle #bundle: # tar cf $(LANG).tar $(LANG).$(FT) $(LANG).$(FG) \ # plainpp.c Makefile $(LANGEX) frame.tex \ # *.pas pprinted.tex README pretzel-latex.sty # release - release: pretzeledpascalpp cp $(LANG)pp ../../bin # # $Log: Makefile,v $ # Revision 2.2 1999/01/19 11:01:18 felix # previous change was not portable over shells. Using a bootstrap # version of pretzel-it (called pretzel-it-bootstrap) to overcome # this. Now the Makefile is not as ``example like'' as praised in # the PretzelBook anymore. # # Revision 2.1 1999/01/19 10:43:13 felix # `make pretzeledpascalpp' jerks at bootstrap time because pretzel-it # hasn't been globally released yet. Add ../../bin temporarily to PATH # to fix this. # # Revision 2.0 1996/12/17 07:52:27 gaertner # *** empty log message *** # # Revision 1.12 1995/09/05 14:58:35 gaertner # Target `release' doesn't copy $(LANG)pp to .. because # `make install' says `make release' here before the library # has been finished. # # Revision 1.11 1995/09/05 14:41:40 gaertner # The generated program is $(LANG)pp now. It always takes the # main program from plainpp.o. # There is a target `simpletest' that uses pretzel-it and `complextest' # that does everything by hand. # Target `release' copies plainpp.o and $(LANG)pp to `..' # # Revision 1.10 1995/08/30 17:52:44 gaertner # Removed pascan.h from bundle line again. # # Revision 1.9 1995/08/30 17:41:18 gaertner # Instead of always producing plainpp, it produces pp # executable. # New target `release' will copy the plainpp.o to the project # directory so that it's available for pretzel-it. # Added pascan.h to the bundle file list. # # Revision 1.8 1995/07/20 09:43:30 gaertner # Changed minimal main program from t to plainpp # # Revision 1.7 1995/04/26 18:29:57 gaertner # README and all .pas files are bundled up now too. # # Revision 1.6 1995/04/26 18:21:55 gaertner # Compiling uses lpretzel library # now. # # Revision 1.5 1994/10/31 19:11:28 gaertner # Now we can make bundle too. # # Revision 1.4 1994/10/24 18:07:48 gaertner # Dependencies are okay now. The makefile uses pretzel and creates # intermediates called *.lex.c and *.tab.c. # # Revision 1.3 1994/10/21 09:52:53 gaertner # The token header is now created correctly and there's a new # target `clean' that removes intermidiate products. # # Revision 1.2 1994/10/20 19:47:42 gaertner # First revision of granny version. # # pretzel-2.0n-2/languages/pascal/frame.tex0000644000000000000000000000075606255451073017117 0ustar rootroot% % $Id: frame.tex,v 2.0 1996/12/17 07:56:41 gaertner Exp $ % \documentstyle[pretzel-latex]{article} \begin{document} \begin{ppcode} \input{pprinted.tex} \end{ppcode} \end{document} % % $Log: frame.tex,v $ % Revision 2.0 1996/12/17 07:56:41 gaertner % *** empty log message *** % % Revision 1.2 1994/10/31 19:51:22 gaertner % Now it's pretzel and not makeWEAVE which is credited for the % prettyprinter. % % Revision 1.1 1994/10/20 19:18:48 gaertner % Initial revision % % pretzel-2.0n-2/languages/pascal/ml.pas0000644000000000000000000000343505445332610016410 0ustar rootrootPROGRAM mathlib (INPUT,OUTPUT); {Nuetzliche Prozeduren} VAR x : REAL; n : INTEGER; FUNCTION Wurzel ( x : REAL ) : REAL; {Berechnet die positive Quadratwurzel von x} VAR x0, x1 : REAL; BEGIN IF x>=0 THEN BEGIN x1:=x; REPEAT x0:=x1; x1:=(x0+x/x0)/2; UNTIL (x0 + abs(x0-x1) = x0); Wurzel:=x1; END ELSE BEGIN WRITELN('Fehler: Wurzel ist komplex!'); END; END; {Wurzel} FUNCTION xhochn ( x : REAL; n : INTEGER ) : REAL; {Berechnet $x^n$ fuer n ganzzahlig} VAR z : REAL; FUNCTION HilfMir ( x : REAL; n : INTEGER ) : REAL; {Vorsicht: Voraussetzung n>=0 } BEGIN IF n=0 THEN HilfMir:=1 ELSE HilfMir:=HilfMir(x,n-1)*x; END; {HilfMir} BEGIN z:=HilfMir(x,abs(n)); IF n<0 THEN z:=1/z; xhochn:=z; END; {xhochn} FUNCTION kteWurzel ( x : REAL; k : INTEGER ) : REAL; {Berechnet die k-te Wurzel von x fuer k ganzzahlig} VAR x0, x1 : REAL; BEGIN IF x>=0 THEN BEGIN x1:=x; REPEAT x0:=x1; x1:=((abs(k)-1)*x0 + x/xhochn(x1,abs(k-1)))/abs(k) UNTIL (x0+abs(x0-x1)=x0); IF k<0 THEN x1:=1/x1; kteWurzel:=x1; END ELSE BEGIN WRITELN('Fehler: Wurzel ist komplex!'); END; END;{kteWurzel} BEGIN WRITELN; WRITELN; WRITELN; WRITELN; WRITELN; WRITELN; WRITELN('Zuerst x'); READLN(x); WRITELN('dann n'); READLN(n); WRITELN; WRITELN; WRITELN; WRITELN; WRITELN; WRITELN; WRITELN('Wurzel(x) ist ',Wurzel(x)); WRITELN('Probe: ',Wurzel(x)*Wurzel(x)); WRITELN('x hoch n ist ',xhochn(x,n)); WRITELN('Probe: ',kteWurzel(xhochn(x,n),n)); WRITELN('n-te Wurzel aus x ist ',kteWurzel(x,n)); WRITELN('Probe: ',xhochn(kteWurzel(x,n),n)); WRITELN; WRITELN; END. pretzel-2.0n-2/languages/pascal/pascal.fg0000644000000000000000000000510406124226404017045 0ustar rootroot/* pretzel formatted grammar for simple PASCAL. */ %token SEMI %token BEG %token END %token MATH // token should only be used in math mode %token SIMP // other simple tokens %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %token COMMENT %token ID_TYPE %token RECORD %token CASE %% stmt_list : stmt // collect everything on a | stmt_list stmt // list of `statements' ; // what can statements be? stmt : COMMENT {cancel + $1} | proc // procedure heading | SEMI // empty statement {cancel + $1 + force } | BEG stmt_list END // a block { $1 + indent + force + $2 + cancel + outdent + force + $3 } | math // an expression ; math : MATH // build something like an | math math // `expression' | simp | COLON | OPEN decl_list CLOSE | RECORD stmt_list END ; simp : SIMP | identifier { "{\\it " + $1 + "}" } ; identifier : ID_TYPE // put together identifiers | identifier ID_TYPE ; decl_list : math // parameter lists | INTRO math // for var-parameters | decl_list SEMI math {$1 + $2 + " " + $3 } | decl_list SEMI INTRO math // for var-parameters ; stmt : ALPHA math OMEGA stmt // if then/while do etc. { $1 + " " + $2 + " " + $3 + indent + force + $4 + outdent } | ALPHA math OMEGA stmt ELSE stmt // if then else {$1 + " " + $2 + " " + $3 + indent + force + $4 + outdent + force + $5 + indent + force + $6 + outdent } | CASE math OMEGA stmt_list END // case of end | BEG stmt_list UNTIL math // repeat until { $1 + indent + force + $2 + cancel + outdent + force + $3 + " " + $4 } ; proc : proc INTRO math SEMI {$1 + $2 + $3 + $4 + force} | PROC // procedure heading ; stmt : INTRO math SEMI // variable and type declarations {$1 + $2 + $3 + force} ; pretzel-2.0n-2/languages/cee/0000755000000000000000000000000006360713177014567 5ustar rootrootpretzel-2.0n-2/languages/cee/complex-example.c0000644000000000000000000000153606255447604020042 0ustar rootroot /* complex example of prettyprinted C code (extract from t1nodes.w) */ mlp = NULL; /* init match list pointer */ mp = mlp; hp = rp->right; /* point |hp| to beginning of round list */ while (hp != NULL) { if (hp->type == matches) { if (mp == NULL) { /* take this node as hew head */ mp = new_node(); check_node(mp); mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ mlp = mp; } else { /* add this one to the back */ mp->left = new_node(); check_node(mp->left); mp = mp->left; mp->type = matches; mp->right = hp->right; mp->left = NULL; /* terminate list */ } } hp = hp->left; /* look at next item of the list */ } pretzel-2.0n-2/languages/cee/fullexample.tex0000644000000000000000000000121706255447604017632 0ustar rootroot\documentclass{article} \usepackage{pretzel-latex} \pagestyle{empty} \begin{document} \title{A Pretzel Prettyprinter for C} \author{Felix G\"artner} \maketitle \section{Example} This document is a simple example of what a section of C code looks like when it has been prettyprinted using the new pretzel prettyprinter for C and \LaTeX. \begin{ppcode} \input{example.tex} \end{ppcode} \noindent The prettyprinter consists of two input files ({\tt cee.ft} and {\tt cee.fg}) that can be tuned to suit ones favours. Through this mechanism, Pretzel allows to build prettyprinters with full user control over the prettyprinting style. \end{document} pretzel-2.0n-2/languages/cee/cee.ft0000644000000000000000000001255206255321415015654 0ustar rootroot/* cee.ft - Felix Gaertner's first pretzel formatted token file for simple C * * target formatter: LaTeX * * $Id: cee.ft,v 1.3 1996/12/16 19:28:54 gaertner Exp $ * * History at end. */ ALPH [a-zA-Z] ALPHNUM [a-zA-Z0-9_] ALPHNUMDOT [a-zA-Z0-9\.] DECDIGIT [0-9] HEXDIGIT [0-9A-Fa-f] EXP ([eE][+-]?[0-9]+) %{ #include // forward declaration of a function that replaces `_' // with `\_' in a copy of s char* escaped_underlines(char* s); %} %% // unary or binary operators for math mode "+" | "-" UNORBINOP "*" UNORBINOP { "\\hbox{$\\ast$}" } "/" | "<" | "=" | ">" | "." | "|" BINOP "%" BINOP { "\\hbox{\\tt\\%}" } "?" QUESTION "!" UNOP "~" UNOP { "\\hbox{\\verb+~+}" } "&" UNORBINOP { "\\&" } "," COMMA { "\\mathout, "} "(" LPAR "[" LBRACK ")" RPAR "]" RBRACK "{" LBRACE { "\\{" } "}" RBRACE { "\\}" } ";" SEMI ":" COLON "++" | "--" UNOP { "\\mbox{\\tt" ** "}" } // binary operators for math mode "!=" BINOP { "\\neq" } "<=" BINOP { "\\leq" } ">=" BINOP { "\\geq" } "==" BINOP { "\\equiv" } "&&" BINOP { "\\land" } "||" BINOP { "\\lor" } "->" BINOP { "\\to" } ">>" BINOP { "\\gg" } "<<" BINOP { "\\ll" } "+=" BINOP { "\\hbox{{\\tt +}=}" } "-=" BINOP { "\\hbox{{\\tt -}=}" } "*=" BINOP { "\\hbox{{\\tt *}=}" } "/=" BINOP { "\\hbox{{\\tt /}=}" } // preprocessor directives: "#" INSERT { "\\#" } "#include" | "#ifdef" | "#ifndef" | "#undef" | "#elif" | "#error" | "#pragma" | "#endif" LPROC { "{\\bf \\" + ** + "}" } "this" | "NULL" NUMBER { "{\\tt " ** "}" } // reserved words: // types and alike: "auto" | "char" | "const" | "double" | "extern" | "FILE" | "float" | "int" | "long" | "register" | "short" | "static" | "unsigned" | "volatile" | "void" | "friend" | "inline" | "virtual" | "signed" INT_LIKE { "{\\bf " + ** + "}" } "enum" | "union" | "class" | "struct" STRUCT_LIKE { "{\\bf " + ** + "}" } "delete" | "new" | "operator" | "sizeof" SIZEOF_LIKE { "{\\bf " + ** + "}" } "define" DEFINE_LIKE { "{\\bf " + ** + "}" } // case statement handling: "break" | "case" | "continue" | "default" | "private" | "protected" | "public" | "template" | "return" CASE_LIKE { "{\\bf " + ** + "}" } "switch" IF_LIKE { "{\\bf " + ** + "}" } // control structures: "do" DO_LIKE { "{\\bf " + ** + "}" } "else" ELSE_LIKE { "{\\bf " + ** + "}" } "for" | "if" | "while" IF_LIKE { "{\\bf " + ** + "}" } // type constructors "typedef" TYPEDEF_LIKE { "{\\bf " + ** + "}" } // comments: "/*"[^\*]*"*/" INSERT // what's this? "<"{ALPHNUMDOT}+">" LPROC { "\n@literal \\verb|" ** "|\n" } // identifiers and constants: [1-9]{DECDIGIT}*[uU]?[lL]? NUMBER 0{DECDIGIT}*[uU]?[lL]? NUMBER // octal 0[xX]{HEXDIGIT}+[uU]?[lL]? NUMBER // hex {DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]? | "."{DECDIGIT}*{EXP}?[fdFD]? | {DECDIGIT}+{EXP}?[fdFD]? | {EXP}[fdFD]? NUMBER // font is added in formatted grammar {ALPH}{ALPHNUM}* ID { [create(escaped_underlines(yytext))] } // strings (relies upon that ^^K is active character in TeX) '([^']|\\')*' | \"([^\"]|\\\")*\" STRING { "\\verb*\013" ** "\013" } [\ \t\n] // gobble up whitespace . // forget all non-standard characters // somehow some strange characters are // sent to pretzel (TODO). forget them. %% // escaped_underines replaces every occurrence of `_' by // the two characters `\_' in a copy of the string pointed to // by s // // the implementation first counts the number of underlines in // the string s and allocates new memory for the string. It then // copies the string byte after byte into the new place and // takes care to insert a `\' before any underline. // // this is a bit dirty as we don't have a chance to free the // allocated space later on, but it's still better than messing // around with yytext. To minimize the amount of memory I have // added a test whether copying is needed or not. char* escaped_underlines(char* s) { char* tmp = s; int number_of_ul = 0; int left = 0; // s[left] is the next char to copy int right = 0; // place s[left] in tmp[right] // fprintf(stderr, "call of escaped_underlines\n"); // count underlines in s while (*tmp != 0) { if (*tmp == '_') number_of_ul++; tmp++; } // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul); if (number_of_ul == 0) { tmp = s; // skip copying } else { tmp = new char[strlen(s) + number_of_ul + 1]; assert(tmp!=NULL); // now start to copy while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but // some compilers choke on it if (s[left] == '_') { tmp[right] = '\\'; right++; } tmp[right] = s[left]; left++; right++; } tmp[right] = s[left]; /* terminate string */ } // fprintf(stderr, "escaped_underlines: in: %s, out: %s\n", s, tmp); return(tmp); } /* * $Log: cee.ft,v $ * Revision 1.3 1996/12/16 19:28:54 gaertner * c without noweb * * Revision 1.1 1996/12/16 19:02:09 gaertner * Initial revision * * Revision 1.1 1996/03/28 11:28:32 gaertner * Initial revision * * Revision 1.2 1996/03/26 14:36:11 gaertner * Getting really ugly now. Maybe I should start with an existing grammar. * * Revision 1.1 1996/03/22 11:25:26 gaertner * Initial revision * */ pretzel-2.0n-2/languages/cee/fullexample.ps0000644000000000000000000025221606124504225017447 0ustar rootroot%!PS-Adobe-2.0 %%Creator: dvipsk 5.58e Copyright 1986, 1994 Radical Eye Software %%Title: fullexample.dvi %%Pages: 1 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%EndComments %DVIPSCommandLine: dvips -o fullexample.ps fullexample.dvi %DVIPSParameters: dpi=600, comments removed %DVIPSSource: TeX output 1996.03.22:1200 %%BeginProcSet: tex.pro /TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} forall round exch round exch]setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ /nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ /sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ 128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff .1 sub]{ch-image}imagemask restore}B /D{/cc X dup type /stringtype ne{]} if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin 0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict /eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V {}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false} ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail {dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ 4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save N}B /eos{SS restore}B end %%EndProcSet TeXDict begin 39158280 55380996 1000 600 600 (fullexample.dvi) @start /Fa 7 120 df<0003FF8000001FFFF000007FFFFC0001FF83FE0003FE007F8007 FC003F800FF8003FC01FF8001FE01FF0001FE03FF0000FF03FF0000FF07FE0000FF07FE0 000FF87FE00007F8FFE00007F8FFE00007F8FFFFFFFFF8FFFFFFFFF8FFFFFFFFF8FFE000 0000FFE0000000FFE0000000FFE00000007FE00000007FE00000007FE00000003FF00000 003FF00000781FF00000780FF80000F80FFC0000F007FC0003F001FF000FE000FFC07FC0 007FFFFF00000FFFFC000001FFE00025257DA42C>101 D<00001FF0000001FFFC000007 FFFF00001FF87F80003FE0FF8000FFC1FFC000FFC1FFC001FF81FFC001FF81FFC003FF01 FFC003FF00FF8003FF00FF8003FF003E0003FF00000003FF00000003FF00000003FF0000 0003FF00000003FF00000003FF00000003FF000000FFFFFF0000FFFFFF0000FFFFFF0000 FFFFFF000003FF00000003FF00000003FF00000003FF00000003FF00000003FF00000003 FF00000003FF00000003FF00000003FF00000003FF00000003FF00000003FF00000003FF 00000003FF00000003FF00000003FF00000003FF00000003FF00000003FF00000003FF00 000003FF00000003FF00000003FF00000003FF00000003FF00000003FF00000003FF0000 0003FF000000FFFFFE0000FFFFFE0000FFFFFE0000FFFFFE0000223A7DB91D>I<00FF00 000000FFFF00000000FFFF00000000FFFF00000000FFFF0000000007FF0000000003FF00 00000003FF0000000003FF0000000003FF0000000003FF0000000003FF0000000003FF00 00000003FF0000000003FF0000000003FF0000000003FF0000000003FF0000000003FF00 00000003FF0000000003FF0000000003FF007FC00003FF03FFF80003FF0FFFFE0003FF1F 03FF0003FF3C01FF8003FF7801FF8003FFF000FF8003FFE000FFC003FFC000FFC003FFC0 00FFC003FF8000FFC003FF8000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF00 00FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF00 00FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF00 00FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC003FF0000FFC0FFFFFC 3FFFFFFFFFFC3FFFFFFFFFFC3FFFFFFFFFFC3FFFFF303A7DB935>104 D<01F00007FC000FFE000FFE001FFF001FFF001FFF001FFF001FFF000FFE000FFE0007FC 0001F00000000000000000000000000000000000000000000000000000000000FF007FFF 007FFF007FFF007FFF0007FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF 0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF 0003FF0003FF0003FF0003FF0003FF0003FF0003FF00FFFFF8FFFFF8FFFFF8FFFFF8153B 7DBA1B>I<00FF00FFFF00FFFF00FFFF00FFFF0007FF0003FF0003FF0003FF0003FF0003 FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003 FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003 FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF0003 FF0003FF0003FF0003FF0003FF0003FF0003FF0003FF00FFFFFCFFFFFCFFFFFCFFFFFC16 3A7DB91B>108 D<003FF03803FFFEF80FFFFFF81FC00FF83F0003F87E0001F87C0000F8 FC0000F8FC000078FE000078FF000078FF800000FFFC0000FFFFE0007FFFFC007FFFFF80 3FFFFFC01FFFFFF00FFFFFF803FFFFF800FFFFFC001FFFFC00007FFE000007FEF00001FE F00000FEF80000FEF800007EFC00007EFC00007CFE0000FCFF0000F8FF8001F8FFF007F0 FFFFFFC0F8FFFF00E01FF8001F257DA426>115 D 119 D E /Fb 4 104 df<7FFFFFFFFFFFF8FFFFFFFFFFFFFCFFFFFFFFFFFFFC7FFFFFFF FFFFF8000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000007FFFFFFFFFFFF8FFFFFFFFFFFFFC FFFFFFFFFFFFFC7FFFFFFFFFFFF800000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000007FFFFF FFFFFFF8FFFFFFFFFFFFFCFFFFFFFFFFFFFC7FFFFFFFFFFFF836267BA741>17 D<0000000000001E00000000000000001E00000000000000001E00000000000000001E00 000000000000001F00000000000000000F00000000000000000F00000000000000000F80 0000000000000007800000000000000007C00000000000000003E00000000000000003E0 0000000000000001F00000000000000000F80000000000000000FC00000000000000007E 00000000000000003F00000000000000001F80000000000000000FC00000000000000007 F07FFFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF FC0000000000000007F0000000000000000FC0000000000000001F80000000000000003F 00000000000000007E0000000000000000FC0000000000000000F80000000000000001F0 0000000000000003E00000000000000003E00000000000000007C0000000000000000780 000000000000000F80000000000000000F00000000000000000F00000000000000001F00 000000000000001E00000000000000001E00000000000000001E00000000000000001E00 00482C7BAA53>33 D<000001F800000FF800003F800000FC000001F8000003F0000007E0 000007E000000FE000000FC000000FC000000FC000000FC000000FC000000FC000000FC0 00000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0 00000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0 00001FC000001F8000003F8000007F000000FE000003F800007FE00000FF0000007FE000 0003F8000000FE0000007F0000003F8000001F8000001FC000000FC000000FC000000FC0 00000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0 00000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC0 00000FC000000FC000000FC000000FC000000FE0000007E0000007E0000003F0000001F8 000000FC0000003F8000000FF8000001F81D537ABD2A>102 DI E /Fc 11 117 df<1C007F00FF80FF80FF80FF80FF80FF80FF80FF80FF80FF 80FF80FF80FF80FF80FF80FF80FF807F007F007F007F007F007F007F007F007F007F007F 007F007F007F007F003E00000000000000000000000000000000001C007F007F00FF80FF 80FF807F007F001C0009346FB32C>33 D<1F003F807FC0FFE0FFE0FFE0FFE0FFE07FC03F 801F000B0B708A2C>46 D<3FFFFFFFE07FFFFFFFF0FFFFFFFFF8FFFFFFFFF8FFFFFFFFF8 7FFFFFFFF000000000000000000000000000000000000000000000000000000000000000 0000000000000000007FFFFFFFF0FFFFFFFFF8FFFFFFFFF8FFFFFFFFF87FFFFFFFF03FFF FFFFE025147DA22C>61 D<7FFFE00000FFFFF00000FFFFF00000FFFFF000007FFFE00000 03F000000003F000000003F000000003F000000003F000000003F000000003F000000003 F000000003F000000003F000000003F000000003F000000003F000000003F000000003F0 00000003F000000003F000000003F000000003F000000003F000000003F000000003F000 000003F000000003F000000003F000000003F000000003F000000003F000000003F00000 0003F000000003F000000003F000000003F00000F003F00001F803F00001F803F00001F8 03F00001F803F00001F803F00001F803F00001F803F00001F87FFFFFFFF8FFFFFFFFF8FF FFFFFFF8FFFFFFFFF87FFFFFFFF025337DB22C>76 D<7FF0007FFCFFF800FFFEFFF800FF FEFFFC00FFFE7FFC007FFC07FE0007C007DE0007C007DE0007C007DF0007C007CF0007C0 07CF0007C007CF8007C007C78007C007C7C007C007C7C007C007C3C007C007C3E007C007 C3E007C007C1E007C007C1F007C007C1F007C007C0F007C007C0F807C007C0F807C007C0 7C07C007C07C07C007C07C07C007C03E07C007C03E07C007C01E07C007C01F07C007C01F 07C007C00F07C007C00F87C007C00F87C007C00787C007C007C7C007C007C7C007C003C7 C007C003E7C007C001E7C007C001E7C007C001F7C007C000F7C007C000F7C007C000FFC0 7FFC007FC0FFFE007FC0FFFE003FC0FFFE003FC07FFC001F8027337EB22C>78 D<7FFF803FFFC0FFFFC07FFFE0FFFFC07FFFE0FFFFC07FFFE07FFF803FFFC003F00001F8 0003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F8 0003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F8 0003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F8 0003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F8 0003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F8 0003F00001F80003F00001F80003F80003F80001F80003F00001F80003F00001FC0007F0 0000FC0007E00000FE000FE000007F001FC000003F803F8000003FE0FF8000001FFFFF00 00000FFFFE00000003FFF800000001FFF0000000003F8000002B3480B22C>85 D<0003FFE000001FFFF800007FFFFE0001FFFFFE0003FFFFFF0007FE00FF000FF000FF00 1FE000FF001FC0007E003F800018003F000000007F000000007E000000007E00000000FC 00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00 0000007E000000007E000000007F000000003F00000F003F80001F801FC0001F801FE000 3F800FF0007F0007FE03FF0003FFFFFE0001FFFFFC00007FFFF800001FFFE0000003FF00 0021247AA32C>99 D<0003FE0000001FFFC000007FFFF00001FFFFF80003FFFFFC0007FE 03FE000FF800FF001FE0003F801FC0003F803F80001FC03F00000FC07F00000FC07E0000 0FE07E000007E0FC000007E0FFFFFFFFE0FFFFFFFFE0FFFFFFFFE0FFFFFFFFE0FFFFFFFF C0FC00000000FE000000007E000000007E000000007F000000003F000003C03F800007E0 1FC00007E00FF0000FE007F8003FC007FF00FFC001FFFFFF8000FFFFFF00003FFFFC0000 0FFFF0000001FF800023247CA32C>101 D<00000FF80000003FFE000000FFFF000001FF FF800003FFFF800007FC7F800007F07F80000FE03F00000FC03F00000FC00000000FC000 00000FC00000000FC00000000FC00000000FC000007FFFFFFE00FFFFFFFF00FFFFFFFF00 FFFFFFFF007FFFFFFE00000FC00000000FC00000000FC00000000FC00000000FC0000000 0FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000F C00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC0 0000000FC00000000FC00000000FC00000000FC00000000FC00000000FC000003FFFFFF0 007FFFFFF8007FFFFFF8007FFFFFF8003FFFFFF00021337DB22C>I<00000003F80007F8 0FFC001FFE3FFE007FFFFFFF01FFFFFFFF03FFFFFE7F03FC0FF87F07F003F83E0FE001FC 1C0FC000FC001FC000FE001F80007E001F80007E001F80007E001F80007E001F80007E00 1F80007E001FC000FE000FC000FC000FE001FC0007F003F80003FC0FF00007FFFFF00007 FFFFE0000FFFFF80000F9FFE00000F87F800000F800000000F800000000F800000000FC0 00000007E000000007FFFFF00003FFFFFE0007FFFFFF800FFFFFFFE01FFFFFFFF03FC000 1FF87F000003FC7E000000FC7C0000007CFC0000007EF80000003EF80000003EF8000000 3EF80000003EFC0000007E7E000000FC7F800003FC3FE0000FF81FFC007FF00FFFFFFFE0 03FFFFFF8001FFFFFF00003FFFF8000007FFC00028387EA42C>I<001E000000003F0000 00003F000000003F000000003F000000003F000000003F000000003F000000003F000000 003F0000007FFFFFFF00FFFFFFFF80FFFFFFFF80FFFFFFFF807FFFFFFF00003F00000000 3F000000003F000000003F000000003F000000003F000000003F000000003F000000003F 000000003F000000003F000000003F000000003F000000003F000000003F000000003F00 0000003F000000003F0003C0003F0007E0003F0007E0003F0007E0003F0007E0003F0007 E0003F800FE0001F801FC0001FE07FC0000FFFFF80000FFFFF000003FFFE000001FFF800 00003FE000232E7EAD2C>116 D E /Fd 19 122 df<0000F800000007FE0000001F871C 00003E03FE00007C03FE0000F801FE0001F801FE0003F000FC0007E000FC000FE000FC00 0FC001FC001FC001F8001FC001F8003F8001F8003F8003F8007F8003F0007F0003F0007F 0003F0007F0007F000FF0007E000FE0007E000FE0007E000FE000FE000FE000FC000FC00 0FC1C0FC000FC1C0FC001FC1C0FC001F83C0FC001F8380FC003F8380FC003F87807C007F 87007C00FF07003E01FF0F003E038F8E001F0F079E0007FE03FC0001F000F000222677A4 2A>97 D<00007F000003FFC0000FC1E0001F0070007E007800FC003801F801F803F003F8 07F003F807E003F80FE003F81FC003F01FC000003F8000003F8000007F8000007F000000 7F0000007F000000FF000000FE000000FE000000FE000000FE000000FC000000FC000000 FC000000FC000030FC000038FC0000787C0000F07E0001E03E0003C03E000F801F003E00 0F81F80003FFE00000FF00001D2677A426>99 D<00000001F8000000FFF8000000FFF800 0000FFF800000003F800000003F000000003F000000007F000000007F000000007E00000 0007E00000000FE00000000FE00000000FC00000000FC00000001FC00000001FC0000000 1F800000001F800000003F800000003F800000F83F000007FE3F00001F877F00003E03FF 00007C03FE0000F801FE0001F801FE0003F000FE0007E000FC000FE000FC000FC001FC00 1FC001FC001FC001F8003F8001F8003F8003F8007F8003F8007F0003F0007F0003F0007F 0007F000FF0007F000FE0007E000FE0007E000FE000FE000FE000FE000FC000FC1C0FC00 0FC1C0FC001FC1C0FC001FC3C0FC001F8380FC003F8380FC003F87807C007F87007C00FF 07003E01FF0F003E038F8E001F0F079E0007FE03FC0001F000F000253B77B92A>I<0000 7F000003FFC0000FC1E0003F00F0007E007800FC007801F8007803F0007807E000780FE0 00780FC000F81FC000F03F8001F03F8007E03F801F807F81FF007FFFF8007FFF00007F00 0000FF000000FE000000FE000000FE000000FE000000FE000000FC000000FC000000FC00 00307C0000387C0000787E0000F03E0001E03E0003C01F000F800F003E000781F80003FF E00000FF00001D2677A426>I<00000007C00000001FF00000003E380000007C3C000000 F8FC000000F9FC000001F9FC000001F1FC000003F1F8000003F0F0000003F000000007F0 00000007E000000007E000000007E000000007E00000000FE00000000FC00000000FC000 00000FC00000000FC00000001FC00000001F8000000FFFFFC0001FFFFFC0001FFFFF8000 003F800000003F000000003F000000003F000000003F000000007F000000007E00000000 7E000000007E000000007E00000000FE00000000FC00000000FC00000000FC00000000FC 00000001FC00000001F800000001F800000001F800000001F800000003F800000003F000 000003F000000003F000000003F000000007F000000007E000000007E000000007E00000 0007E00000000FE00000000FC00000000FC00000000FC00000001FC00000001F80000000 1F800000001F800000001F000000003F0000001C3F0000007E3E0000007E3E000000FE3C 000000FE7C000000FE78000000F8F000000078F00000003FC00000000F80000000264C82 BA19>I<000007C00000003FF0000000FC38E00001F01FF00003E01FF00007C00FF0000F 800FF0001F8007F0003F0007E0007F0007E0007E000FE000FE000FE000FC000FC001FC00 0FC001FC001FC003FC001FC003F8001F8003F8001F8003F8003F8007F8003F8007F0003F 0007F0003F0007F0007F0007F0007F0007E0007E0007E0007E0007E000FE0007E000FE00 07E000FC0003E001FC0003E003FC0003E007FC0001F00FF80000F01FF80000787BF80000 3FF3F800000FC3F000000003F000000007F000000007F000000007E000000007E0000000 0FE00000000FC0001C000FC0007E001FC0007E001F8000FE003F0000FE007E0000FE00FC 00007801F800007C07E000001FFF80000003FE00000024367CA426>I<0003F0000001FF F0000001FFF0000001FFF000000007F000000007E000000007E000000007E00000000FE0 0000000FC00000000FC00000000FC00000001FC00000001F800000001F800000001F8000 00003F800000003F000000003F000000003F000000007F000000007E07F000007E1FFC00 007E783E0000FFE01F0000FFC01F8000FF800F8000FF000F8001FE000F8001FE000FC001 FC000FC001F8001F8003F8001F8003F0001F8003F0001F8003F0003F8007F0003F0007E0 003F0007E0003F0007E0007F000FE0007E000FC0007E000FC000FE000FC000FC001FC000 FC001F8001FC1C1F8001F81C1F8001F83C3F8003F8383F0003F0383F0003F0383F0003F0 707F0003E0707E0003E0F07E0003E0E07E0003E1C0FE0001E380FC0000FF003800003C00 263B7BB92A>I<0001C00007E00007F0000FF0000FE00007E00003800000000000000000 0000000000000000000000000000000000000000000000000000F00003FC00071E000E1F 001C1F001C1F00381F00383F00703F00703F00707F00F07E00E07E00E0FE0000FC0000FC 0001FC0001F80003F80003F80003F00007F00007E00007E0000FE0E00FC0E00FC1E01FC1 C01F81C01F81C01F83801F03801F07001F07001F0E000F1C0007F80001E000143879B619 >I<0003F0000001FFF0000001FFF0000001FFF000000007F000000007E000000007E000 000007E00000000FE00000000FC00000000FC00000000FC00000001FC00000001F800000 001F800000001F800000003F800000003F000000003F000000003F000000007F00000000 7E000F80007E003FE0007E00F0E000FE01C1F000FC0387F000FC0707F000FC0E07F001FC 1C07E001F83807E001F830038001F870000003F8E0000003F1C0000003F380000003FF00 000007FC00000007FE00000007FFC0000007E7F800000FE1FC00000FC07E00000FC07F00 000FC03F00001FC03F80001F801F81C01F801F81C01F801F83C03F803F83803F003F0380 3F003F03803F003F07807F003F07007E003E07007E001E0E007E001E1E00FE000F3C00FC 0007F800380001E000243B7BB926>107 D<000FC007FFC007FFC007FFC0001FC0001F80 001F80003F80003F80003F00003F00007F00007F00007E00007E0000FE0000FE0000FC00 00FC0001FC0001FC0001F80001F80003F80003F80003F00003F00007F00007F00007E000 07E0000FE0000FE0000FC0000FC0001FC0001FC0001F80001F80003F80003F80003F0000 3F00007F00007F00007E0E007E0E00FE0E00FE1E00FC1C00FC1C00FC3C00FC3800F83800 F878007870007CE0001FE0000F8000123B79B915>I<01E000FE0007F00007F803FF801F FC000E3C0F07C0783E001E3E3C03E1E01F001C1F7803F3C01F80383FF001F7800F80383F E001F7000F80783FC001FE000F80703FC001FE000FC0703F8001FC000FC0703F0003F800 1F80F07F0003F8001F80E07E0003F0001F80E07E0003F0001F80007E0007F0003F8000FE 0007F0003F0000FC0007E0003F0000FC0007E0003F0000FC000FE0007F0001FC000FE000 7E0001F8000FC0007E0001F8000FC000FE0001F8001FC000FC0003F8001FC000FC0003F0 001F8001FC1C03F0001F8001F81C03F0003F8001F83C07F0003F8003F83807E0003F0003 F03807E0003F0003F03807E0007F0003F0700FE0007F0003E0700FC0007E0003E0F00FC0 007E0003E0E00FC000FE0003E1C01FC000FE0001E3C01F8000FC0000FF00070000380000 3C003E2679A444>I<01E000FE000007F803FF80000E3C0F07C0001E3E3C03E0001C1F78 03F000383FF001F000383FE001F000783FC001F000703FC001F800703F8001F800703F00 03F000F07F0003F000E07E0003F000E07E0003F000007E0007F00000FE0007E00000FC00 07E00000FC0007E00000FC000FE00001FC000FC00001F8000FC00001F8001FC00001F800 1F800003F8001F800003F0003F838003F0003F038003F0003F078007F0007F070007E000 7E070007E0007E070007E0007E0E000FE0007C0E000FC0007C1E000FC0007C1C000FC000 7C38001FC0003C78001F80001FE000070000078000292679A42F>I<00007F000003FFC0 000FC1F0001F00F8007E007C00FC007C01F8007E03F0003E07F0003F07E0003F0FE0003F 1FC0003F1FC0003F3F80003F3F80007F7F80007F7F00007F7F00007F7F0000FFFF0000FF FE0000FEFE0000FEFE0001FEFE0001FCFC0001FCFC0003F8FC0003F8FC0007F0FC0007E0 FC000FE07C000FC07E001F803E003F003E007E001F00F8000F83F00003FFC00000FE0000 202677A42A>I<00078007C000001FE03FF000003CF0787C000038F8E03E0000787FC03E 0000707F801F000070FF001F0000F0FE001F8000E0FE001F8000E0FC001F8001E1FC001F 8001C1FC001F8001C1F8001F8001C1F8001F800003F8003F800003F8003F800003F0003F 800003F0003F800007F0007F800007F0007F800007E0007F000007E0007F00000FE000FF 00000FE000FE00000FC000FE00000FC001FC00001FC001FC00001FC001F800001F8003F8 00001F8003F000003F8007E000003FC00FC000003FC00F8000003FE01F0000007FE03E00 00007F70FC0000007E3FF00000007E0F80000000FE0000000000FE0000000000FC000000 0000FC0000000001FC0000000001FC0000000001F80000000001F80000000003F8000000 0003F80000000003F00000000007F000000000FFFFC0000000FFFFC0000000FFFFC00000 00293580A42A>I<03C003F0000FF01FFC001E783C0F001C7C700F003C3EE03F80383FC0 3F80387F803F80787F803F00707F003F00707F001C00F07E000000E0FE000000E0FC0000 00E0FC00000000FC00000001FC00000001F800000001F800000001F800000003F8000000 03F000000003F000000003F000000007F000000007E000000007E000000007E00000000F E00000000FC00000000FC00000000FC00000001FC00000001F800000001F800000001F80 0000003F800000003F000000000E00000000212679A423>114 D<0000FE000007FF8000 0F83C0003E00E0007C00F00078007000F800F001F803F001F003F001F003F001F003E003 F001C003F8000003FC000003FFC00001FFF80001FFFE0000FFFF00007FFF80003FFF8000 0FFFC00000FFC000003FC000001FC000000FC03E000FC07E000FC0FE000F80FE000F80FE 000F80FC001F00E0001F00F0003E0070007C003800F8001E03E0000FFFC00001FE00001C 267AA422>I<0003800007C0000FC0000FC0000FC0000FC0001FC0001F80001F80001F80 003F80003F00003F00003F00007F00007E007FFFFF7FFFFFFFFFFF00FC0000FC0000FC00 01FC0001F80001F80001F80003F80003F00003F00003F00007F00007E00007E00007E000 0FE0000FC0000FC0000FC0001FC0001F801C1F801C1F803C3F80383F00783F00703F00F0 3F00E03F01C03E03C01F07800F0F0007FC0001F000183579B31C>I<00F0000000070003 FC0003801F80071E0007C03FC00E1F000FC03FC01C1F000FC03FC03C1F000FC03FC0381F 001FC01FC0383F001F800FC0703F001F8007C0703F001F8007C0707F003F8007C0F07E00 3F800780E07E003F000380E0FE003F00038000FC007F00078000FC007F00070001FC007E 00070001F8007E00070001F800FE000F0003F800FE000E0003F000FC000E0003F000FC00 0E0003F000FC001E0007F001FC001C0007E001F8001C0007E001F8003C0007E001F80038 0007E001F800380007E001F800780007E001F800700007E003F800F00007E003F800E000 03E007F801E00003F00FFC03C00001F01E7C07800000FC3C3E0F0000003FF81FFE000000 0FE003F00000322679A437>119 D<00F000000003FC0001C0071E0003E00E1F0007E01C 1F0007E03C1F0007E0381F000FE0383F000FC0703F000FC0703F000FC0707F001FC0F07E 001F80E07E001F80E0FE001F8000FC003F8000FC003F0001FC003F0001F8003F0001F800 7F0003F8007E0003F0007E0003F0007E0003F000FE0007F000FC0007E000FC0007E000FC 0007E001FC0007E001F80007E001F80007E001F80007E003F80007E003F00007E007F000 03E00FF00003F01FF00001F87FE000007FF7E000001FC7E00000000FE00000000FC00000 000FC00000001FC0003F001F80007F003F80007F003F00007F007E00007F007C00007E00 FC00007001F800007003E000003807C000003C1F8000000FFE00000003F0000000233679 A428>121 D E /Fe 1 66 df<00000E00000000000E00000000001F00000000001F0000 0000001F00000000003F80000000003F80000000003F80000000006FC0000000006FC000 000000EFE000000000C7E000000000C7E00000000183F00000000183F00000000183F000 00000301F80000000301F80000000601FC0000000600FC0000000600FC0000000C007E00 00000C007E0000001C007F00000018003F00000018003F00000030003F8000003FFFFF80 00003FFFFF80000060000FC0000060000FC00000E0000FE00000C00007E00000C00007E0 0001800003F00001800003F00003800003F80003800001F80007800001F8001FC00003FC 00FFF8003FFFE0FFF8003FFFE02B2A7EA931>65 D E /Ff 41 125 df<00000FF8000000007FFE00000001F80780000007E001C000001F8000E000003F0007 E000007E000FF000007E000FF00000FC000FF00000FC000FF00001F8000FF00001F80007 E00001F80001800001F80000000001F80000000001F80000000001F80000000001F80000 000001F80000000001F80000000001F80000000001F80000000001F80003F000FFFFFFFF F000FFFFFFFFF000FFFFFFFFF00001F8000FF00001F80003F00001F80003F00001F80003 F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003 F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003 F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003 F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003F00001F80003 F00001F80003F00003FC0007F8007FFFE0FFFFC07FFFE0FFFFC07FFFE0FFFFC02A3B7FBA 2E>12 D<0000600000E00001C0000380000700000E00001E00003C0000780000780000F0 0001E00001E00003C00003C00007C0000780000F80000F00000F00001F00001E00001E00 003E00003E00003E00007C00007C00007C00007C00007C00007C0000F80000F80000F800 00F80000F80000F80000F80000F80000F80000F80000F80000F80000F80000F80000F800 00F80000F80000F800007C00007C00007C00007C00007C00007C00003E00003E00003E00 001E00001E00001F00000F00000F00000F800007800007C00003C00003C00001E00001E0 0000F000007800007800003C00001E00000E000007000003800001C00000E00000601352 78BD20>40 DI<000380000007C0000007C0000007C0000007C0000007C0000007C00000 07C0007803803CFC03807EFE0380FE7F8383FC3FC387F80FE38FE003FBBF8000FFFE0000 3FF800000FE000000FE000003FF80000FFFE0003FBBF800FE38FE03FC387F87F8383FCFE 0380FEFC03807E7803803C0007C0000007C0000007C0000007C0000007C0000007C00000 07C000000380001F247BBD2A>I<1C007F00FF80FF80FFC0FFC0FFC07FC01CC000C000C0 00C000C001C00180018003800300070006000E001C003800700060000A19798817>44 D<1C007F00FF80FF80FF80FF80FF807F001C000909798817>46 D<0000000C0000001E00 00003E0000003E0000003C0000007C0000007C00000078000000F8000000F8000000F000 0001F0000001F0000001E0000003E0000003E0000003C0000007C0000007C00000078000 000F8000000F8000000F0000001F0000001F0000001E0000003E0000003E0000003C0000 007C0000007C00000078000000F8000000F8000000F0000001F0000001F0000001E00000 03E0000003E0000007C0000007C00000078000000F8000000F8000000F0000001F000000 1F0000001E0000003E0000003E0000003C0000007C0000007C00000078000000F8000000 F8000000F0000001F0000001F0000001E0000003E0000003E0000003C0000007C0000007 C00000078000000F8000000F8000000F0000001F0000001F0000001E0000003E0000003E 0000003C0000007C0000007C00000078000000F8000000F8000000F0000000600000001F 537BBD2A>I<0001C0000003C0000007C000001FC00000FFC000FFFFC000FFFFC000FF1F C000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001F C000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001F C000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001F C000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001F C000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000003F E0007FFFFFF07FFFFFF07FFFFFF01C3879B72A>49 D<1C007F00FF80FF80FF80FF80FF80 7F001C000000000000000000000000000000000000000000000000000000000000000000 000000001C007F00FF00FF80FF80FF80FF807F801D800180018001800180038003000300 0700060006000E001C001800380070006000093479A317>59 D<7FFFFFFFFFFFF8FFFFFF FFFFFFFCFFFFFFFFFFFFFCFFFFFFFFFFFFFC000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000FFFFFFFFFFFFFCFFFFFFFFFFFFFCFFFFFFFFFFFFFC7FFFFFFFFFFFF8 36167B9F41>61 D<000001FF80018000000FFFE0038000007FFFF803800001FF807E0780 0003FC000F0F80000FF000039F80001FE00001DF80003F800000FF80007F0000007F8000 FE0000003F8001FE0000003F8003FC0000001F8007F80000000F8007F80000000F800FF0 00000007800FF000000007801FE000000007801FE000000003803FE000000003803FC000 000003807FC000000001807FC000000001807FC000000001807F800000000180FF800000 000000FF800000000000FF800000000000FF800000000000FF800000000000FF80000000 0000FF800000000000FF800000000000FF800000000000FF800000000000FF8000000000 00FF800000000000FF8000000000007F8000000000007FC000000001807FC00000000180 7FC000000001803FC000000001803FE000000001801FE000000003801FE000000003000F F000000003000FF0000000070007F8000000070007F8000000060003FC0000000E0001FE 0000001C0000FE0000001800007F0000003800003F8000007000001FE00000E000000FF0 0003C0000003FC000F80000001FF803F000000007FFFFC000000000FFFF00000000001FF 800000313D7BBA3C>67 D69 D76 D 80 D<3FFFFFFFFFFFE03FFFFFFFFFFFE03FFFFFFFFFFFE03FC003FF001FE03E0001FE00 03E07C0001FE0001F0780001FE0000F0700001FE000070700001FE000070700001FE0000 70600001FE000030600001FE000030600001FE000030600001FE000030E00001FE000038 C00001FE000018C00001FE000018C00001FE000018C00001FE000018000001FE00000000 0001FE000000000001FE000000000001FE000000000001FE000000000001FE0000000000 01FE000000000001FE000000000001FE000000000001FE000000000001FE000000000001 FE000000000001FE000000000001FE000000000001FE000000000001FE000000000001FE 000000000001FE000000000001FE000000000001FE000000000001FE000000000001FE00 0000000001FE000000000001FE000000000001FE000000000001FE000000000001FE0000 00000001FE000000000001FE000000000001FE000000000001FE000000000001FE000000 000001FE000000000001FE000000000007FF800000001FFFFFFFE000001FFFFFFFE00000 1FFFFFFFE00035397DB83C>84 D<7FFFFF003FFFFC007FFFFF003FFFFC007FFFFF003FFF FC0000FFF80007FF8000007FE00003FC0000003FE00001F00000001FF00001E00000001F F00001C00000000FF800018000000007FC00038000000007FC00070000000003FE000600 00000003FE000E0000000001FF001C0000000000FF80180000000000FF80380000000000 7FC03000000000003FE06000000000003FE0E000000000001FF0C000000000000FF18000 000000000FFB80000000000007FF00000000000007FE00000000000003FE000000000000 01FF00000000000001FF00000000000000FF800000000000007FC00000000000007FC000 0000000000FFE0000000000000DFE00000000000019FF00000000000038FF80000000000 030FF800000000000607FC00000000000E03FE00000000000C03FE00000000001801FF00 000000003800FF00000000003000FF800000000060007FC000000000E0007FC000000000 C0003FE00000000180001FF00000000380001FF00000000300000FF800000006000007FC 0000000E000007FC0000000C000003FE0000001C000001FE0000003C000001FF000000FE 000001FF800007FF800007FFE000FFFFE0003FFFFF80FFFFE0003FFFFF80FFFFE0003FFF FF8039397EB83E>88 D<001FE0000000FFFC000003E03F000007000F80000F8007E0001F C003F0001FE003F0001FE001F8001FE001F8001FE000FC000FC000FC00078000FC000000 00FC00000000FC00000000FC00000000FC0000007FFC000007FFFC00003FE0FC0000FE00 FC0003F800FC000FF000FC001FC000FC003FC000FC007F8000FC007F0000FC007F0000FC 0CFE0000FC0CFE0000FC0CFE0000FC0CFE0001FC0CFE0001FC0CFF0003FC0C7F00077C0C 7F80063E183FC01E3E180FE0781FF003FFF00FE0007F8007C026277DA52A>97 D<03F0000000FFF0000000FFF0000000FFF00000000FF000000003F000000003F0000000 03F000000003F000000003F000000003F000000003F000000003F000000003F000000003 F000000003F000000003F000000003F000000003F000000003F000000003F000000003F0 1FE00003F07FF80003F1E03E0003F3801F8003F7000FC003FE0007E003FC0003F003F800 01F803F00001F803F00000FC03F00000FC03F00000FE03F00000FE03F000007E03F00000 7F03F000007F03F000007F03F000007F03F000007F03F000007F03F000007F03F000007F 03F000007F03F000007F03F000007E03F00000FE03F00000FE03F00000FC03F00001FC03 F80001F803F80003F003FC0003F003EE0007E003C6000FC003C7801F000381E07E000300 FFF80000001FC000283B7EB92E>I<0003FC00001FFF80007E03E001F8007003F000F807 E001FC0FC003FC0FC003FC1F8003FC3F8003FC3F0001F87F0000F07F0000007F0000007E 000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE 000000FE0000007E0000007F0000007F0000003F0000063F8000061F80000E1FC0000C0F C0001C07E0003803F0007001F800E0007C07C0001FFF000007F8001F277DA525>I<0000 000FC0000003FFC0000003FFC0000003FFC00000003FC00000000FC00000000FC0000000 0FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00000000F C00000000FC00000000FC00000000FC00000000FC00000000FC00000000FC00003F80FC0 001FFF0FC0007E078FC000F801EFC003F0007FC007E0003FC00FC0001FC00FC0001FC01F 80000FC03F80000FC03F00000FC07F00000FC07F00000FC07E00000FC0FE00000FC0FE00 000FC0FE00000FC0FE00000FC0FE00000FC0FE00000FC0FE00000FC0FE00000FC0FE0000 0FC0FE00000FC07E00000FC07F00000FC07F00000FC03F00000FC03F00000FC01F80001F C01F80001FC00FC0003FC007E0007FC003F000EFF001F801CFFF007C078FFF001FFE0FFF 0007F80FC0283B7DB92E>I<0007F800001FFF00007C0FC001F803E003F001F007E001F8 0FC000F81F80007C1F80007C3F00007E3F00003E7F00003E7F00003F7E00003FFE00003F FE00003FFE00003FFFFFFFFFFFFFFFFFFE000000FE000000FE000000FE000000FE000000 7E0000007E0000007F0000007F0000003F0000033F8000031F8000070FC0000607C0000E 07E0001C01F0003800F80070007E03E0001FFF800003FC0020277EA525>I<00007E0000 03FF80000FC1E0001F87E0003F0FF0007E0FF0007E0FF000FC0FF000FC0FF001F803C001 F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001 F8000001F8000001F8000001F80000FFFFFC00FFFFFC00FFFFFC0001F8000001F8000001 F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001 F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001 F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000003 FC00007FFFF8007FFFF8007FFFF8001C3B7FBA19>I<00000003F0000FF00FF8003FFC3C 3C00F81F707C01F00FE07C03E007C07C07C003E0100FC003F0000FC003F0001F8001F800 1F8001F8001F8001F8001F8001F8001F8001F8001F8001F8001F8001F8001F8001F8000F C003F0000FC003F00007C003E00003E007C00003F00F800003F81F0000073FFC0000060F F000000E000000000E000000000E000000000E000000000F000000000F000000000FC000 000007FFFFC00007FFFFF80003FFFFFE0001FFFFFF8003FFFFFFC00F80007FE01F00000F F03E000003F07C000001F07C000001F8F8000000F8F8000000F8F8000000F8F8000000F8 F8000000F8FC000001F87C000001F03E000003E03F000007E00F80000F8007E0003F0001 FC01FC00007FFFF0000007FF000026387EA52A>I<03F000000000FFF000000000FFF000 000000FFF0000000000FF00000000003F00000000003F00000000003F00000000003F000 00000003F00000000003F00000000003F00000000003F00000000003F00000000003F000 00000003F00000000003F00000000003F00000000003F00000000003F00000000003F000 00000003F00FF0000003F03FFC000003F0F03F000003F1C01F800003F3800FC00003F700 0FC00003FE000FC00003FC0007E00003FC0007E00003F80007E00003F80007E00003F800 07E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F000 07E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F000 07E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F000 07E00003F00007E00003F00007E00003F00007E00007F8000FF000FFFFC1FFFF80FFFFC1 FFFF80FFFFC1FFFF80293A7EB92E>I<0380000FE0001FF0001FF0001FF0001FF0001FF0 000FE0000380000000000000000000000000000000000000000000000000000000000000 0003F000FFF000FFF000FFF00007F00003F00003F00003F00003F00003F00003F00003F0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00007F800FFFFC0FFFF C0FFFFC012387EB717>I<03F0000000FFF0000000FFF0000000FFF00000000FF0000000 03F000000003F000000003F000000003F000000003F000000003F000000003F000000003 F000000003F000000003F000000003F000000003F000000003F000000003F000000003F0 00000003F000000003F000000003F001FFFC03F001FFFC03F001FFFC03F0007FC003F000 7F0003F0007C0003F000700003F000E00003F001C00003F003800003F007000003F01E00 0003F038000003F078000003F0FC000003F1FC000003F3FE000003F73F000003FE3F8000 03F81F800003F00FC00003F00FE00003F007E00003F003F00003F001F80003F001FC0003 F000FC0003F0007E0003F0007F0003F0003F0003F0003F8003F0001FC007F8003FF0FFFF C0FFFFFFFFC0FFFFFFFFC0FFFF283A7EB92C>107 D<03F000FFF000FFF000FFF0000FF0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F0 0003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F00003F0 0003F00007F800FFFFC0FFFFC0FFFFC0123A7EB917>I<03F00FF0001FE000FFF03FFC00 7FF800FFF0F03F01E07E00FFF1C01F83803F000FF3800FC7001F8003F7000FCE001F8003 FE000FDC001F8003FC0007F8000FC003FC0007F8000FC003F80007F0000FC003F80007F0 000FC003F80007F0000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003 F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0 000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003 F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0 000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC003F00007E0000FC007 F8000FF0001FE0FFFFC1FFFF83FFFFFFFFC1FFFF83FFFFFFFFC1FFFF83FFFF40257EA445 >I<03F00FF00000FFF03FFC0000FFF0F03F0000FFF1C01F80000FF3800FC00003F7000F C00003FE000FC00003FC0007E00003FC0007E00003F80007E00003F80007E00003F80007 E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007 E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007 E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007 E00003F00007E00003F00007E00003F00007E00007F8000FF000FFFFC1FFFF80FFFFC1FF FF80FFFFC1FFFF8029257EA42E>I<0003FE0000000FFF8000003E03E00000F800F80001 F0007C0003E0003E0007C0001F000F80000F801F80000FC01F000007C03F000007E03F00 0007E07E000003F07E000003F07E000003F07E000003F0FE000003F8FE000003F8FE0000 03F8FE000003F8FE000003F8FE000003F8FE000003F8FE000003F8FE000003F87E000003 F07E000003F07F000007F03F000007E03F000007E01F80000FC00F80000F800FC0001F80 07E0003F0003F0007E0000F800F800007E03F000001FFFC0000003FE000025277EA52A> I<03F01FE000FFF07FF800FFF1E07E00FFF3801F8007F7000FC003FE0007E003FC0003F0 03F80003F803F00001F803F00001FC03F00000FC03F00000FE03F00000FE03F00000FE03 F000007F03F000007F03F000007F03F000007F03F000007F03F000007F03F000007F03F0 00007F03F000007F03F000007F03F00000FE03F00000FE03F00000FE03F00001FC03F000 01FC03F80003F803F80003F003FC0007F003FE000FE003F6000FC003F7803F0003F1E07E 0003F0FFF80003F01FC00003F000000003F000000003F000000003F000000003F0000000 03F000000003F000000003F000000003F000000003F000000003F000000007F8000000FF FFC00000FFFFC00000FFFFC0000028357EA42E>I<07E01F00FFE07FC0FFE1E3E0FFE387 F00FE707F003E607F003EE07F003EC03E003FC008003F8000003F8000003F8000003F800 0003F0000003F0000003F0000003F0000003F0000003F0000003F0000003F0000003F000 0003F0000003F0000003F0000003F0000003F0000003F0000003F0000003F0000003F000 0003F0000003F0000007F80000FFFFF000FFFFF000FFFFF0001C257EA421>114 D<00FF030003FFE7000F80FF001E003F003C001F0078000F0070000700F0000700F00007 00F0000300F8000300F8000300FC000300FF0000007FE000007FFF00003FFFE0001FFFF8 000FFFFC0003FFFE0000FFFF000007FF8000007F8000001F80C0000FC0C00007C0C00007 C0E00003C0E00003C0E00003C0F00003C0F0000380F8000780FC000780FC000F00FF001E 00F3C07C00E1FFF000C03F80001A277DA521>I<00180000001800000018000000180000 0018000000380000003800000038000000780000007800000078000000F8000001F80000 03F8000007F800001FFFFF00FFFFFF00FFFFFF0001F8000001F8000001F8000001F80000 01F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F80000 01F8000001F8000001F8000001F8000001F8000001F800C001F800C001F800C001F800C0 01F800C001F800C001F800C001F800C001F800C000FC01C000FC0180007C0380007E0300 003F0700000FFE000001F8001A347FB220>I<03F00007E000FFF001FFE000FFF001FFE0 00FFF001FFE0000FF0001FE00003F00007E00003F00007E00003F00007E00003F00007E0 0003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E0 0003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E0 0003F00007E00003F00007E00003F00007E00003F00007E00003F00007E00003F00007E0 0003F0000FE00003F0000FE00003F0000FE00003F0001FE00001F0001FE00001F8003FE0 0000F80077F80000FC00E7FF80003F03C7FF80001FFF87FF800003FC07E00029267EA42E >IIIII<3FFFFFFC3FFFFFFC3F8003FC3E0003F83C 0007F038000FE030000FE070001FC070003F8060007F8060007F006000FE006001FC0060 01FC000003F8000007F0000007F000000FE000001FC000003F8000003F8000007F000600 FE000600FE000601FC000603F8000607F8000E07F0000E0FE0000C1FC0001C1FC0001C3F 80003C7F00007CFF0003FCFFFFFFFCFFFFFFFC1F247EA325>I124 D E /Fg 8 121 df<000000780000000000FC0000000003FC0000000007FC000000001FFC00000000FFFC 0000000FFFFC000007FFFFFC0000FFFFFFFC0000FFFFFFFC0000FFFF7FFC0000FFF07FFC 0000F8007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC000000007FFC 000000007FFC00007FFFFFFFFFFE7FFFFFFFFFFE7FFFFFFFFFFE7FFFFFFFFFFE7FFFFFFF FFFE2F4E76CD43>49 D69 D<00007FFF000000000007FFFFF0000000003FFFFFFE00000000FFFFFFFF80000001FFE0 0FFFC0000003FE0001FFF0000007FF0000FFF8000007FF80003FFC00000FFF80003FFE00 000FFFC0001FFE00000FFFC0001FFF00000FFFC0000FFF80000FFFC0000FFF80000FFFC0 000FFF800007FF800007FFC00007FF800007FFC00003FF000007FFC00001FE000007FFC0 000000000007FFC0000000000007FFC0000000000007FFC0000000000007FFC000000000 0007FFC0000000000007FFC0000000007FFFFFC00000000FFFFFFFC0000000FFFFFFFFC0 000007FFFF87FFC000003FFFF007FFC000007FFF8007FFC00001FFFC0007FFC00003FFF0 0007FFC00007FFE00007FFC0000FFFC00007FFC0001FFF800007FFC0003FFF000007FFC0 007FFF000007FFC0007FFE000007FFC0007FFE000007FFC000FFFC000007FFC000FFFC00 0007FFC000FFFC000007FFC000FFFC000007FFC000FFFC00000FFFC000FFFC00000FFFC0 00FFFE00001FFFC0007FFE00001DFFC0007FFE00003DFFC0003FFF000079FFE0001FFF80 00F1FFF8000FFFC003E1FFFFE007FFF81FC0FFFFF003FFFFFF807FFFF000FFFFFF001FFF F0001FFFFC0007FFE00001FFE0000000003C387CB641>97 D<000003FFC0000000003FFF FC00000001FFFFFF00000007FFFFFFC000000FFF81FFE000003FFC007FF800007FF8003F FC0000FFF0001FFE0001FFE0000FFE0003FFC00007FF0007FFC00007FF800FFF800003FF 800FFF800003FFC01FFF800001FFC01FFF000001FFC03FFF000001FFE03FFF000001FFE0 7FFF000000FFE07FFE000000FFE07FFE000000FFF07FFE000000FFF0FFFE000000FFF0FF FE000000FFF0FFFE000000FFF0FFFE000000FFF0FFFFFFFFFFFFF0FFFFFFFFFFFFF0FFFF FFFFFFFFF0FFFFFFFFFFFFE0FFFE0000000000FFFE0000000000FFFE0000000000FFFE00 00000000FFFE0000000000FFFE00000000007FFE00000000007FFE00000000007FFF0000 0000003FFF00000000003FFF00000000003FFF00000000E01FFF00000001F01FFF800000 03F00FFF80000003F007FFC0000007E007FFC0000007E003FFE000000FC001FFF000001F C000FFF800003F80007FFC0000FF00001FFE0003FE00000FFFC03FF8000003FFFFFFF000 0000FFFFFFC00000001FFFFE0000000001FFF0000034387CB63D>101 D<003FF000FFFFF000FFFFF000FFFFF000FFFFF000FFFFF00001FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF00000FFF0 0000FFF00000FFF00000FFF00000FFF00000FFF00000FFF000FFFFFFF0FFFFFFF0FFFFFF F0FFFFFFF0FFFFFFF01C537BD225>108 D<003FF0001FFC000000FFE00000FFFFF000FF FFC00007FFFE0000FFFFF003FFFFF0001FFFFF8000FFFFF00FFFFFF8007FFFFFC000FFFF F01FE07FFC00FF03FFE000FFFFF03F001FFE01F800FFF00003FFF07C001FFF03E000FFF8 0000FFF0F0000FFF0780007FF80000FFF1E0000FFF8F00007FFC0000FFF3C0000FFF9E00 007FFC0000FFF7800007FFBC00003FFC0000FFF7800007FFFC00003FFE0000FFFF000007 FFF800003FFE0000FFFE000007FFF000003FFE0000FFFE000007FFF000003FFE0000FFFC 000007FFE000003FFE0000FFFC000007FFE000003FFE0000FFFC000007FFE000003FFE00 00FFFC000007FFE000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC00000 3FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FF C000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF800 0007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000 FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003F FE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC0 00003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF80000 07FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FF F8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE 0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000 003FFE0000FFF8000007FFC000003FFE0000FFF8000007FFC000003FFE0000FFF8000007 FFC000003FFE00FFFFFFF807FFFFFFC03FFFFFFEFFFFFFF807FFFFFFC03FFFFFFEFFFFFF F807FFFFFFC03FFFFFFEFFFFFFF807FFFFFFC03FFFFFFEFFFFFFF807FFFFFFC03FFFFFFE 67367BB570>I<003FF001FFE0000000FFFFF00FFFFE000000FFFFF03FFFFFC00000FFFF F0FFFFFFF00000FFFFF3FF01FFF80000FFFFF7F8007FFE000003FFFFE0001FFF000000FF FF80000FFF800000FFFF000007FFC00000FFFE000007FFE00000FFFC000003FFF00000FF F8000001FFF80000FFF8000001FFF80000FFF8000000FFFC0000FFF8000000FFFC0000FF F8000000FFFE0000FFF80000007FFE0000FFF80000007FFF0000FFF80000007FFF0000FF F80000007FFF0000FFF80000007FFF0000FFF80000003FFF8000FFF80000003FFF8000FF F80000003FFF8000FFF80000003FFF8000FFF80000003FFF8000FFF80000003FFF8000FF F80000003FFF8000FFF80000003FFF8000FFF80000003FFF8000FFF80000003FFF8000FF F80000003FFF8000FFF80000003FFF8000FFF80000003FFF0000FFF80000007FFF0000FF F80000007FFF0000FFF80000007FFF0000FFF80000007FFE0000FFF8000000FFFE0000FF F8000000FFFE0000FFF8000000FFFC0000FFF8000001FFFC0000FFF8000001FFF80000FF FC000003FFF00000FFFC000003FFF00000FFFE000007FFE00000FFFF00000FFFC00000FF FF80001FFF800000FFFFC0003FFF000000FFFFF000FFFC000000FFFBFE07FFF8000000FF F8FFFFFFE0000000FFF87FFFFF80000000FFF81FFFFC00000000FFF803FFC000000000FF F800000000000000FFF800000000000000FFF800000000000000FFF800000000000000FF F800000000000000FFF800000000000000FFF800000000000000FFF800000000000000FF F800000000000000FFF800000000000000FFF800000000000000FFF800000000000000FF F800000000000000FFF800000000000000FFF800000000000000FFF800000000000000FF F8000000000000FFFFFFF80000000000FFFFFFF80000000000FFFFFFF80000000000FFFF FFF80000000000FFFFFFF80000000000414D7BB54B>112 D<7FFFFFF0007FFFFE007FFF FFF0007FFFFE007FFFFFF0007FFFFE007FFFFFF0007FFFFE007FFFFFF0007FFFFE00007F FE00000FFF0000003FFF000007F80000001FFF800007F00000000FFFC0000FE000000007 FFC0001FC000000007FFE0003F8000000003FFF0003F0000000001FFF8007E0000000000 FFFC00FC00000000007FFE01FC00000000007FFE03F800000000003FFF07F00000000000 1FFF8FE000000000000FFFCFC0000000000007FFFF80000000000003FFFF000000000000 03FFFF00000000000001FFFE00000000000000FFFC000000000000007FFE000000000000 003FFF000000000000003FFF000000000000001FFF800000000000001FFFC00000000000 003FFFE00000000000007FFFF0000000000000FFFFF0000000000001FDFFF80000000000 01F8FFFC000000000003F07FFE000000000007E03FFF00000000000FE01FFF0000000000 1FC01FFF80000000003F800FFFC0000000007F0007FFE000000000FE0003FFF000000000 FC0001FFF800000001F80001FFF800000003F00000FFFC00000007F000007FFE0000000F E000003FFF0000001FC000001FFF800000FFF000001FFF8000FFFFFE0001FFFFFFC0FFFF FE0001FFFFFFC0FFFFFE0001FFFFFFC0FFFFFE0001FFFFFFC0FFFFFE0001FFFFFFC04235 7EB447>120 D E /Fh 19 128 df<1E007F80FF80FFC0FFC0FFE0FFE0FFE07FE01E6000 6000600060006000E000C000C000C001C0018003800300070006000E001C003800700060 000B1D78891B>44 D<000030000000F0000001F0000003F000001FF00000FFF000FFFFF0 00FFE7F000FF07F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 00000FF800001FFC007FFFFFFF7FFFFFFF7FFFFFFF204278C131>49 D<0003FE0000001FFFC000007FFFF00001F80FFC0003C001FE00078000FF000E00007F80 1C00003FC01C00001FE03800001FF03000000FF07000000FF860000007F86C000007F8FF 000007FCFF800007FCFFC00007FCFFC00003FCFFC00003FCFFC00003FCFFC00003FC7F80 0007FC3F000007FC00000007FC00000007F800000007F80000000FF80000000FF0000000 1FF00000001FE00000001FE00000003FC00000007F800000007F00000000FF00000000FE 00000001FC00000003F800000007F000000007E00000000FC00000001F800000003F0000 00007C00000000F800000000F000000001E000000003C000000007800000000F00000C00 1E00000C003C00000C0038000018007000001800E000001801C000001803800000380700 0000300E000000701FFFFFFFF01FFFFFFFF03FFFFFFFF07FFFFFFFF0FFFFFFFFE0FFFFFF FFE0FFFFFFFFE026427BC131>I<000007FC0000003FFF000000FFFFC00003FC03E00007 E000F0001FC00038003F000058007E0001FC00FE0003FC00FC0007FC01F80007FC03F000 07FC03F00007FC07E00003F80FE00001F00FE00000001FC00000001FC00000001FC00000 003F800000003F800000003F800000007F800000007F800000007F007F80007F01FFF000 7F0780FC00FF0E003E00FF1C001F80FF38000FC0FF700007E0FF600007E0FFE00003F0FF C00003F8FFC00001F8FFC00001FCFF800001FCFF800000FEFF800000FEFF800000FEFF00 0000FFFF000000FFFF000000FFFF000000FF7F000000FF7F000000FF7F000000FF7F0000 00FF7F000000FF7F800000FF3F800000FF3F800000FF3F800000FE1F800000FE1F800001 FE1FC00001FC0FC00001FC0FC00003F807E00003F807E00007F003F00007E001F8000FC0 00FC001F80007E003F00003F80FE00000FFFF8000003FFE0000000FF800028447CC131> 54 D<0000FF00000007FFE000001FFFF800007F80FC0000FC007E0001F8003F0003F000 1F8007E0000FC00FE00007E01FC00007E01FC00003F03F800003F03F800003F87F800001 F87F000001FC7F000001FCFF000001FCFF000001FCFF000001FEFF000000FEFF000000FE FF000000FEFF000000FEFF000000FEFF000000FFFF000000FFFF000000FFFF000000FF7F 000001FF7F000001FF7F000001FF3F800001FF3F800003FF1F800003FF1FC00003FF0FC0 0007FF07E00006FF07E0000EFF03F0001CFF01F80038FF007C0070FF003F01E0FF000FFF 80FE0001FE00FE00000000FE00000001FE00000001FC00000001FC00000001FC00000001 FC00000003F800000003F800000003F00F800007F01FC00007E03FE0000FE03FE0000FC0 3FE0001F803FE0001F803FC0003F003F80007E001E0000FC001C0001F8000F0003F00007 E01FE00003FFFF800000FFFE0000001FF0000028447CC131>57 D70 D<0000000FFE00006000000000FFFFC000E000000003FFFFF000E0000000 0FFC01FC01E00000003FC0003E01E0000000FF00000F83E0000003FC000003C7E0000007 F8000001E7E000000FF0000000FFE000001FE00000007FE000003FC00000003FE000007F 800000001FE00000FF000000000FE00001FE000000000FE00001FC0000000007E00003FC 0000000007E00007F80000000003E00007F80000000003E0000FF00000000001E0000FF0 0000000001E0001FE00000000000E0001FE00000000000E0003FE00000000000E0003FE0 0000000000E0003FC0000000000060007FC0000000000060007FC0000000000060007FC0 000000000060007FC000000000000000FF8000000000000000FF8000000000000000FF80 00000000000000FF8000000000000000FF8000000000000000FF8000000000000000FF80 00000000000000FF8000000000000000FF8000000000000000FF8000000000000000FF80 00000000000000FF8000000000000000FF8000000000000000FF80000001FFFFFFC07FC0 000001FFFFFFC07FC0000001FFFFFFC07FC0000000007FF0007FC0000000003FE0003FC0 000000001FE0003FE0000000001FE0003FE0000000001FE0001FE0000000001FE0001FF0 000000001FE0000FF0000000001FE0000FF0000000001FE00007F8000000001FE00007F8 000000001FE00003FC000000001FE00001FE000000001FE00001FE000000001FE00000FF 000000001FE000007F800000001FE000003FC00000003FE000001FE00000003FE000000F F00000007FE0000007F8000000E7E0000003FE000001C7E0000000FF00000383E0000000 3FE0000F01E00000000FFC00FE00E000000003FFFFF8006000000000FFFFE00000000000 000FFE0000000042487BC54D>I77 D<0007FC000000003FFF80000000F80FE00000 03C003F00000070001F800000E0000FC00000FC0007E00001FE0007F00001FF0003F8000 1FF0003F80001FF0003F80001FF0001FC0001FF0001FC0000FE0001FC0000380001FC000 0000001FC0000000001FC0000000001FC0000000001FC00000000FFFC0000001FFFFC000 000FFE1FC000003FC01FC00000FF001FC00003FC001FC00007F8001FC0000FF0001FC000 1FE0001FC0003FC0001FC0007FC0001FC0007F80001FC0007F80001FC060FF00001FC060 FF00001FC060FF00001FC060FF00003FC060FF00003FC060FF00003FC060FF80007FC060 7F8000EFC0607FC000C7E0C03FC001C7E0C01FE00783F1C007F81E03FF8001FFFC01FF00 001FE0007C002B2E7CAC31>97 D<00007F80000003FFF000000FC07C00003F000F0000FC 00038001F80001C003F8000FC007F0001FE007E0003FE00FE0003FE01FC0003FE01FC000 3FE03F80003FE03F80001FC07F800007007F800000007F800000007F00000000FF000000 00FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000 FF00000000FF00000000FF000000007F000000007F800000007F800000003F800000003F 800000303FC00000301FC00000700FE00000600FE00000E007F00000C003F80001C001F8 00038000FC000700003F001E00001FC078000007FFF0000000FF8000242E7DAC2B>99 D<0001FE00000007FFC000001F03F000007E00FC0000FC007E0001F8003F0003F0003F00 07E0001F800FE0001FC00FC0000FC01FC0000FC03F80000FE03F800007E03F800007E07F 800007F07F000007F07F000007F0FF000007F0FF000007F0FF000007F0FFFFFFFFF0FFFF FFFFF0FF00000000FF00000000FF00000000FF00000000FF00000000FF000000007F0000 00007F000000007F800000007F800000003F800000003F800000301FC00000301FC00000 700FC00000600FE00000E007F00000C003F00001C001F800038000FC000700003E001E00 001F80F8000003FFE0000000FF0000242E7DAC2B>101 D<01FC00000000FFFC00000000 FFFC00000000FFFC0000000007FC0000000003FC0000000001FC0000000001FC00000000 01FC0000000001FC0000000001FC0000000001FC0000000001FC0000000001FC00000000 01FC0000000001FC0000000001FC0000000001FC0000000001FC0000000001FC00000000 01FC0000000001FC0000000001FC0000000001FC0000000001FC0000000001FC01FE0000 01FC07FFC00001FC1E07F00001FC3801F80001FC7001FC0001FCE000FC0001FDC000FE00 01FD8000FE0001FF80007F0001FF00007F0001FF00007F0001FE00007F0001FE00007F00 01FE00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F00 01FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F00 01FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F00 01FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F00 01FC00007F0001FC00007F0001FC00007F0003FE0000FF80FFFFF83FFFFEFFFFF83FFFFE FFFFF83FFFFE2F457DC436>104 D<01E00007F80007F8000FFC000FFC000FFC000FFC00 07F80007F80001E000000000000000000000000000000000000000000000000000000000 00000000000000000000000001FC00FFFC00FFFC00FFFC0007FC0003FC0001FC0001FC00 01FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC00 01FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC00 01FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0003FE00FFFFF8FFFFF8FFFFF8 15437DC21C>I<01FC00FFFC00FFFC00FFFC0007FC0003FC0001FC0001FC0001FC0001FC 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC0001FC 0001FC0001FC0001FC0001FC0001FC0001FC0001FC0003FE00FFFFF8FFFFF8FFFFF81545 7DC41C>108 D<01FC01FE0000FFFC07FFC000FFFC1E07F000FFFC3801F80007FC7001FC 0003FCE000FC0001FDC000FE0001FD8000FE0001FF80007F0001FF00007F0001FF00007F 0001FE00007F0001FE00007F0001FE00007F0001FC00007F0001FC00007F0001FC00007F 0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F 0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F 0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F 0001FC00007F0001FC00007F0001FC00007F0001FC00007F0001FC00007F0003FE0000FF 80FFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFE2F2C7DAB36>110 D<03F803F0FFF81FFCFFF83C3EFFF8707F07F8E0FF03F9C0FF01F980FF01FB80FF01FB00 7E01FB003C01FF000001FE000001FE000001FE000001FE000001FC000001FC000001FC00 0001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC00 0001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC000001FC00 0001FC000001FC000001FC000001FC000003FF0000FFFFFE00FFFFFE00FFFFFE00202C7D AB26>114 D<0006000000060000000600000006000000060000000E0000000E0000000E 0000000E0000001E0000001E0000001E0000003E0000007E0000007E000000FE000001FE 000007FE00001FFFFFF0FFFFFFF0FFFFFFF000FE000000FE000000FE000000FE000000FE 000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE 000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE000000FE 000C00FE000C00FE000C00FE000C00FE000C00FE000C00FE000C00FE000C00FE000C00FE 000C007E001C007F0018007F0018003F0038001F8030001FC0700007E0E00001FFC00000 7F001E3E7EBC26>116 D120 D<1E0007807F000FE0FF80 1FF0FFC03FF0FFC03FF0FFC03FF0FFC03FF0FF801FF07F000FE01E0007801C0A76C231> 127 D E /Fi 14 123 df<00000000000F00000000000000000000000F00000000000000 000000000F00000000000000000000001F80000000000000000000001F80000000000000 000000003FC0000000000000000000003FC0000000000000000000003FC0000000000000 000000007FE0000000000000000000007FE0000000000000000000007FE0000000000000 00000000FFF000000000000000000000FFF000000000000000000000FFF0000000000000 00000001FFF800000000000000000001DFF800000000000000000001DFF8000000000000 000000039FFC000000000000000000038FFC000000000000000000038FFC000000000000 000000070FFE0000000000000000000707FE0000000000000000000F07FF000000000000 0000000E03FF0000000000000000000E03FF0000000000000000001E03FF800000000000 0000001C01FF8000000000000000001C01FF8000000000000000003C01FFC00000000000 0000003800FFC000000000000000003800FFC000000000000000007000FFE00000000000 00000070007FE0000000000000000070007FE00000000000000000E0007FF00000000000 000000E0003FF00000000000000000E0003FF00000000000000001C0003FF80000000000 000001C0001FF80000000000000003C0001FFC000000000000000380000FFC0000000000 00000380000FFC000000000000000780000FFE0000000000000007000007FE0000000000 000007000007FE000000000000000F000007FF000000000000000E000003FF0000000000 00000E000003FF000000000000001C000003FF800000000000001C000001FF8000000000 00001C000001FF8000000000000038000001FFC000000000000038000000FFC000000000 000038000000FFC000000000000070000000FFE0000000000000700000007FE000000000 0000F00000007FF0000000000000E00000003FF0000000000000E00000003FF000000000 0001E00000003FF8000000000001C00000001FF8000000000001C00000001FF800000000 0003C00000001FFC000000000003FFFFFFFFFFFC000000000003FFFFFFFFFFFC00000000 0007FFFFFFFFFFFE000000000007FFFFFFFFFFFE0000000000070000000007FE00000000 000E0000000007FF00000000000E0000000003FF00000000000E0000000003FF00000000 001C0000000003FF80000000001C0000000001FF80000000003C0000000001FFC0000000 00380000000000FFC000000000380000000000FFC000000000780000000000FFE0000000 007000000000007FE0000000007000000000007FE000000000F000000000007FF0000000 00E000000000003FF000000000E000000000003FF000000001C000000000003FF8000000 01C000000000001FF800000001C000000000001FF8000000038000000000001FFC000000 038000000000000FFC000000038000000000000FFC000000070000000000000FFE000000 0700000000000007FE0000000F00000000000007FF0000000F00000000000003FF000000 1F00000000000003FF0000003F80000000000003FF8000007FC0000000000003FF800001 FFE0000000000007FFC0000FFFF800000000001FFFF000FFFFFF0000000007FFFFFFF0FF FFFF0000000007FFFFFFF0FFFFFF0000000007FFFFFFF0FFFFFF0000000007FFFFFFF05C 657DE463>65 D<00000000007FF800000060000000000FFFFF800000E0000000007FFFFF E00000E000000003FFFFFFFC0001E00000000FFFE003FE0001E00000003FFE00003F8003 E0000000FFF0000007C003E0000001FFC0000003F007E0000007FF00000000F80FE00000 0FFC000000007C0FE000001FF8000000001E1FE000007FE0000000000F1FE00000FFC000 00000007BFE00001FF800000000003FFE00003FF000000000003FFE00007FE0000000000 01FFE0000FFC000000000000FFE0000FF80000000000007FE0001FF00000000000007FE0 003FF00000000000003FE0007FE00000000000001FE0007FC00000000000001FE000FFC0 0000000000000FE001FF800000000000000FE001FF800000000000000FE003FF00000000 00000007E003FF0000000000000007E007FE0000000000000003E007FE00000000000000 03E00FFC0000000000000003E00FFC0000000000000001E01FFC0000000000000001E01F FC0000000000000001E01FF80000000000000001E03FF80000000000000001E03FF80000 000000000000E03FF00000000000000000E03FF00000000000000000E07FF00000000000 000000E07FF00000000000000000007FF00000000000000000007FF00000000000000000 007FF0000000000000000000FFE0000000000000000000FFE0000000000000000000FFE0 000000000000000000FFE0000000000000000000FFE0000000000000000000FFE0000000 000000000000FFE0000000000000000000FFE0000000000000000000FFE0000000000000 000000FFE0000000000000000000FFE0000000000000000000FFE0000000000000000000 FFE0000000000000000000FFE0000000000000000000FFE0000000000000000000FFE000 00000000000000007FF00000000000000000007FF00000000000000000007FF000000000 00000000007FF00000000000000000007FF00000000000000000003FF000000000000000 00003FF00000000000000000E03FF80000000000000000E03FF80000000000000000E01F F80000000000000000E01FFC0000000000000000E01FFC0000000000000000E00FFC0000 000000000001E00FFC0000000000000001C007FE0000000000000001C007FE0000000000 000001C003FF0000000000000001C003FF0000000000000003C001FF8000000000000003 8001FF80000000000000078000FFC00000000000000780007FC00000000000000700007F E00000000000000F00003FF00000000000001E00001FF00000000000001E00000FF80000 000000003C00000FFC00000000000038000007FE00000000000078000003FF0000000000 00F0000001FF800000000001E0000000FFC00000000003C00000007FE00000000007C000 00001FF8000000000F800000000FFC000000001F0000000007FF000000007C0000000001 FFC0000001F80000000000FFF0000007F000000000003FFE00001FC000000000000FFFE0 01FF00000000000003FFFFFFFC000000000000007FFFFFF0000000000000000FFFFF8000 000000000000007FF80000000053667AE360>67 D80 D<000003FE00000000001FFFE000000000FFFFF800000001FE03FE00000007F0007F8000 000FE0003FC000003FC0001FE000007F00000FF00000FF000007F80000FE000003F80001 FC000003FC0003F8000001FC0007F8000001FE0007F0000000FE000FF0000000FF000FF0 0000007F001FE00000007F001FE00000007F803FE00000007F803FC00000003F803FC000 00003F807FC00000003FC07FC00000003FC07FC00000003FC07F800000003FC07F800000 003FC0FF800000003FC0FFFFFFFFFFFFC0FFFFFFFFFFFFC0FFFFFFFFFFFFC0FF80000000 0000FF800000000000FF800000000000FF800000000000FF800000000000FF8000000000 00FF800000000000FF800000000000FF8000000000007F8000000000007FC00000000000 7FC000000000007FC000000000003FC000000000003FC000000000003FE000000000001F E000000000001FE000000001C00FF000000001C00FF000000003C007F8000000038007F8 000000038003FC000000078001FC0000000F0001FE0000000E0000FF0000001E00007F80 00003C00003FC000007800001FE00000F0000007F00003E0000003FC0007C0000000FF80 3F000000003FFFFC000000000FFFF00000000001FF80000032417CBF3A>101 D<0000000FF0000000007FFC00000001FFFF00000007F81F8000000FE00FC000001FC03F C000003F807FE000007F007FE00000FF007FE00001FE007FE00001FC007FE00003FC003F C00003FC003FC00007F8000F000007F80000000007F8000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000FFFFFFFFF000FFFFFFFFF000FFFFFFFFF0 00FFFFFFFFF000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000000FF00000 00000FF0000000000FF0000000000FF0000000000FF0000000000FF0000000001FF80000 00003FFE0000003FFFFFFF00003FFFFFFF00003FFFFFFF00003FFFFFFF00002B657EE428 >I<003C000000FF000001FF800003FFC00003FFC00003FFC00003FFC00003FFC00003FF C00001FF800000FF0000003C000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000003C00007FFC0007FFFC0007FFF C0007FFFC0007FFFC00001FFC000007FC000007FC000003FC000003FC000003FC000003F C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000007F E00000FFF000FFFFFFE0FFFFFFE0FFFFFFE0FFFFFFE01B5F7DDE23>105 D<0003C00007FFC000FFFFC000FFFFC000FFFFC000FFFFC00001FFC000007FC000007FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 00003FC000003FC000003FC000003FC000007FE00000FFF000FFFFFFF0FFFFFFF0FFFFFF F0FFFFFFF01C647DE323>108 D<0003C0007FE000000007FFC003FFFC000000FFFFC00F FFFF000000FFFFC03F00FFC00000FFFFC078001FE00000FFFFC0F0000FF0000001FFC1C0 0007F80000007FC3800007FC0000007FC7000003FC0000003FCE000003FE0000003FCE00 0001FE0000003FDC000001FE0000003FD8000001FE0000003FF8000000FF0000003FF000 0000FF0000003FF0000000FF0000003FF0000000FF0000003FE0000000FF0000003FE000 0000FF0000003FE0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000003FC0000000FF0000003FC000 0000FF0000003FC0000000FF0000003FC0000000FF0000007FE0000001FF800000FFF000 0003FFC000FFFFFFF003FFFFFFC0FFFFFFF003FFFFFFC0FFFFFFF003FFFFFFC0FFFFFFF0 03FFFFFFC0423F7DBE49>110 D<000000FF8000000000000FFFF800000000003FFFFE00 00000000FF007F8000000003FC001FE000000007F00007F00000000FC00001F80000003F 800000FE0000007F0000007F0000007E0000003F000000FC0000001F800001F80000000F C00003F80000000FE00003F000000007E00007F000000007F0000FE000000003F8000FE0 00000003F8001FE000000003FC001FC000000001FC001FC000000001FC003FC000000001 FE003FC000000001FE003FC000000001FE007F8000000000FF007F8000000000FF007F80 00000000FF007F8000000000FF00FF8000000000FF80FF8000000000FF80FF8000000000 FF80FF8000000000FF80FF8000000000FF80FF8000000000FF80FF8000000000FF80FF80 00000000FF80FF8000000000FF80FF8000000000FF80FF8000000000FF80FF8000000000 FF807F8000000000FF007F8000000000FF007FC000000001FF007FC000000001FF003FC0 00000001FE003FC000000001FE003FC000000001FE001FE000000003FC001FE000000003 FC001FE000000003FC000FF000000007F80007F000000007F00007F000000007F00003F8 0000000FE00001FC0000001FC00001FC0000001FC00000FE0000003F8000007F0000007F 0000003F800000FE0000001FC00001FC0000000FF00007F800000003FC001FE000000000 FF007F80000000007FFFFF00000000000FFFF8000000000001FFC000000039417CBF42> I<0003C0007FC000000007FFC007FFFC000000FFFFC01FFFFF000000FFFFC07F00FFC000 00FFFFC0F8001FF00000FFFFC3E00007F8000001FFC7800003FC0000007FCF000001FE00 00007FDE000000FF0000003FFC0000007F8000003FF80000003FC000003FF00000003FE0 00003FF00000001FE000003FE00000001FF000003FE00000000FF800003FC00000000FF8 00003FC000000007FC00003FC000000007FC00003FC000000003FE00003FC000000003FE 00003FC000000003FE00003FC000000001FF00003FC000000001FF00003FC000000001FF 00003FC000000001FF00003FC000000001FF80003FC000000000FF80003FC000000000FF 80003FC000000000FF80003FC000000000FF80003FC000000000FF80003FC000000000FF 80003FC000000000FF80003FC000000000FF80003FC000000000FF80003FC000000000FF 80003FC000000000FF80003FC000000000FF80003FC000000001FF00003FC000000001FF 00003FC000000001FF00003FC000000001FF00003FC000000001FF00003FC000000003FE 00003FC000000003FE00003FC000000003FC00003FC000000007FC00003FC000000007FC 00003FC00000000FF800003FE00000000FF000003FE00000001FF000003FF00000003FE0 00003FF80000003FC000003FF80000007FC000003FFC000000FF8000003FDE000001FF00 00003FCF000003FE0000003FC7800007FC0000003FC3C0000FF00000003FC1F0003FE000 00003FC07E01FF800000003FC03FFFFE000000003FC00FFFF8000000003FC000FF800000 00003FC0000000000000003FC0000000000000003FC0000000000000003FC00000000000 00003FC0000000000000003FC0000000000000003FC0000000000000003FC00000000000 00003FC0000000000000003FC0000000000000003FC0000000000000003FC00000000000 00003FC0000000000000003FC0000000000000003FC0000000000000003FC00000000000 00003FC0000000000000003FC0000000000000003FC0000000000000003FC00000000000 00003FC0000000000000007FE000000000000000FFF0000000000000FFFFFFF000000000 00FFFFFFF00000000000FFFFFFF00000000000FFFFFFF00000000000415B7DBE49>I<00 078003F80007FF800FFF00FFFF803FFFC0FFFF807C0FE0FFFF81F01FE0FFFF81E03FF001 FF83803FF0007F87003FF0007F8F003FF0003F8E003FF0003F9C001FE0003F9C000FC000 3F98000300003FB8000000003FB8000000003FB0000000003FF0000000003FF000000000 3FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FC000000000 3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 3FC0000000003FC0000000003FC0000000003FC0000000003FC0000000003FC000000000 3FC0000000003FC0000000003FC0000000007FE000000000FFF8000000FFFFFFFC0000FF FFFFFC0000FFFFFFFC0000FFFFFFFC00002C3F7CBE33>114 D<00003800000000003800 000000003800000000003800000000003800000000003800000000003800000000007800 00000000780000000000780000000000780000000000F80000000000F80000000000F800 00000001F80000000001F80000000001F80000000003F80000000003F80000000007F800 0000000FF8000000001FF8000000001FF8000000007FF800000000FFF800000003FFF800 00000FFFFFFFFF00FFFFFFFFFF00FFFFFFFFFF00FFFFFFFFFF000007F80000000007F800 00000007F80000000007F80000000007F80000000007F80000000007F80000000007F800 00000007F80000000007F80000000007F80000000007F80000000007F80000000007F800 00000007F80000000007F80000000007F80000000007F80000000007F80000000007F800 00000007F80000000007F80000000007F80000000007F80000000007F80000000007F800 00000007F80000000007F80000000007F80000000007F80000000007F80000000007F800 00000007F80000E00007F80000E00007F80000E00007F80000E00007F80000E00007F800 00E00007F80000E00007F80000E00007F80000E00007F80000E00007F80000E00007F800 00E00007F80000E00007F80000E00003FC0001C00003FC0001C00003FC0001C00003FC00 03C00001FE0003800001FE0007800000FF00070000007F800F0000003FC01E0000001FF0 7C0000000FFFF800000003FFE0000000007F80002B597FD733>116 D121 D<1FFFFFFFFFFF801FFFFFFFFFFF801FFFFFFFFFFF801FFF000001FF001FF8000003FF00 1FE0000003FE001F80000007FC001F8000000FFC001F0000001FF8001E0000001FF0001E 0000003FE0003C0000007FE0003C0000007FC0003C000000FF80003C000001FF80003C00 0001FF000038000003FE000038000007FE00003800000FFC00003800000FF80000380000 1FF000003800003FF000003800003FE000000000007FC00000000000FFC00000000000FF 800000000001FF000000000003FF000000000003FE000000000007FC00000000000FFC00 000000001FF800000000001FF000000000003FE000000000007FE000000000007FC00000 000000FF800003800001FF800003800001FF000003800003FE000003800007FE00000380 0007FC00000380000FF800000700001FF800000700003FF000000700003FE00000070000 7FC00000070000FFC00000070000FF8000000F0001FF0000000F0003FF0000000F0003FE 0000001F0007FC0000001F000FFC0000003F001FF80000007F001FF0000000FE003FE000 0001FE007FE0000007FE007FC000007FFE00FFFFFFFFFFFE00FFFFFFFFFFFE00FFFFFFFF FFFE00313E7DBD3A>I E end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%PaperSize: a4 %%EndSetup %%Page: 1 1 1 0 bop 1105 822 a Fi(A)44 b(Pretzel)h(Prett)l(yprin)l(ter)f(for)f(C) 1660 1063 y Fh(F)-8 b(elix)31 b(G\177)-49 b(artner)1619 1258 y(Marc)m(h)33 b(22,)g(1996)515 1616 y Fg(1)134 b(Example)515 1797 y Ff(This)26 b(do)r(cumen)n(t)g(is)g(a)g(simple)h(example)e(of)i (what)f(a)g(section)f(of)i(C)f(co)r(de)g(lo)r(oks)f(lik)n(e)h(when)515 1897 y(it)i(has)f(b)r(een)h(prett)n(yprin)n(ted)f(using)g(the)h(new)g (pretzel)f(prett)n(yprin)n(ter)g(for)g(C)g(and)h(L)3150 1880 y Fe(A)3187 1897 y Ff(T)3233 1915 y(E)3279 1897 y(X.)681 2080 y(/*)e(complex)i(example)f(of)g(prett)n(yprin)n(ted)g(C)h (co)r(de)g(\(extract)f(from)g(t1no)r(des.w\))g(*/)598 2179 y Fd(mlp)i Ff(=)22 b Fc(NULL)o Ff(;)83 b(/*)26 b(init)j(matc)n(h)e (list)h(p)r(oin)n(ter)f(*/)598 2279 y Fd(mp)h Ff(=)23 b Fd(mlp)6 b Ff(;)598 2379 y Fd(hp)29 b Ff(=)23 b Fd(rp)28 b Fb(!)23 b Fd(right)9 b Ff(;)83 b(/*)27 b(p)r(oin)n(t)g(|hp|)h(to)g(b) r(eginning)f(of)h(round)f(list)h(*/)598 2478 y Fa(while)e Ff(\()p Fd(hp)7 b Fc(!=)o(NULL)n Ff(\))28 b Fb(f)681 2578 y Fa(if)f Ff(\()p Fd(hp)j Fb(!)23 b Fd(typ)l(e)29 b Fb(\021)23 b Fd(matches)7 b Ff(\))28 b Fb(f)764 2678 y Fa(if)f Ff(\()p Fd(mp)i Fb(\021)23 b Fc(NULL)n Ff(\))28 b Fb(f)83 b Ff(/*)26 b(tak)n(e)h(this)h(no)r(de)g(as)f(hew)g(head)h(*/) 847 2777 y Fd(mp)g Ff(=)23 b Fd(new)p 1227 2777 25 4 v 39 w(no)l(de)7 b Ff(\(\);)847 2877 y Fd(che)l(ck)p 1052 2877 V 40 w(no)l(de)f Ff(\()p Fd(mp)g Ff(\);)847 2976 y Fd(mp)28 b Fb(!)c Fd(typ)l(e)29 b Ff(=)23 b Fd(matches)7 b Ff(;)847 3076 y Fd(mp)28 b Fb(!)c Fd(right)31 b Ff(=)23 b Fd(hp)29 b Fb(!)23 b Fd(right)9 b Ff(;)847 3176 y Fd(mp)28 b Fb(!)c Fd(left)31 b Ff(=)23 b Fc(NULL)n Ff(;)83 b(/*)27 b(terminate)g(list)h(*/)847 3275 y Fd(mlp)h Ff(=)22 b Fd(mp)6 b Ff(;)764 3375 y Fb(g)27 b Fa(else)f Fb(f)83 b Ff(/*)27 b(add)g(this)h(one)f(to)h(the)g(bac)n(k)e(*/)847 3475 y Fd(mp)i Fb(!)c Fd(left)31 b Ff(=)23 b Fd(new)p 1477 3475 V 38 w(no)l(de)7 b Ff(\(\);)847 3574 y Fd(che)l(ck)p 1052 3574 V 40 w(no)l(de)f Ff(\()p Fd(mp)29 b Fb(!)23 b Fd(left)9 b Ff(\);)847 3674 y Fd(mp)28 b Ff(=)23 b Fd(mp)29 b Fb(!)23 b Fd(left)8 b Ff(;)847 3773 y Fd(mp)28 b Fb(!)c Fd(typ)l(e)29 b Ff(=)23 b Fd(matches)7 b Ff(;)847 3873 y Fd(mp)28 b Fb(!)c Fd(right)31 b Ff(=)23 b Fd(hp)29 b Fb(!)23 b Fd(right)9 b Ff(;)847 3973 y Fd(mp)28 b Fb(!)c Fd(left)31 b Ff(=)23 b Fc(NULL)n Ff(;)83 b(/*)27 b(terminate)g(list)h (*/)764 4072 y Fb(g)681 4172 y(g)681 4272 y Fd(hp)h Ff(=)23 b Fd(hp)29 b Fb(!)23 b Fd(left)8 b Ff(;)83 b(/*)27 b(lo)r(ok)g(at)g (next)h(item)g(of)g(the)g(list)g(*/)598 4371 y Fb(g)515 4653 y Ff(The)i(prett)n(yprin)n(ter)f(consists)g(of)h(t)n(w)n(o)g (input)h(\014les)f(\()p Fc(cee.ft)e Ff(and)i Fc(cee.fg)p Ff(\))e(that)i(can)g(b)r(e)515 4753 y(tuned)35 b(to)f(suit)h(ones)f(fa) n(v)n(ours.)56 b(Through)33 b(this)i(mec)n(hanism,)h(Pretzel)e(allo)n (ws)f(to)i(build)515 4853 y(prett)n(yprin)n(ters)26 b(with)i(full)g (user)f(con)n(trol)g(o)n(v)n(er)e(the)j(prett)n(yprin)n(ting)f(st)n (yle.)1926 5205 y(1)p eop %%Trailer end userdict /end-hook known{end-hook}if %%EOF pretzel-2.0n-2/languages/cee/cee.fg0000644000000000000000000001720106255321415015633 0ustar rootroot/* cee.fg - Felix Gaertner's first formatted grammar for C * target is LaTeX * * $Id: cee.fg,v 1.3 1996/12/16 19:28:54 gaertner Exp $ * * History at end. */ %token BINOP %token UNORBINOP %token QUESTION %token UNOP %token LPAR %token RPAR %token LBRACE %token RBRACE %token LBRACK %token RBRACK %token SEMI %token COLON %token LPROC %token ID %token NUMBER %token INT_LIKE %token CASE_LIKE %token IF_LIKE %token DO_LIKE %token ELSE_LIKE %token TYPEDEF_LIKE %token STRUCT_LIKE %token SIZEOF_LIKE %token DEFINE_LIKE %token COMMA %token INSERT %token STRING %{ #include #include #include /* these functions help to typeset typedefs. they implement * a simple lookup table to see if an identifier is a * typedef or what... * * taken from Kernighan/Ritchie: The C Programming Language, p.144ff */ struct nlist { /* a table entry: */ struct nlist *next; /* next entry in chain */ char* name; /* the identifier */ }; #define HASHSIZE 101 static struct nlist* hashtab[HASHSIZE]; /* the hash table */ /* form the hash value of a string */ static unsigned hash(char* s) { // cerr << "hash(" << s << ") called." << endl; unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = *s + 31 * hashval; return hashval % HASHSIZE; } /* lookup: look for s in hashtab * * returns a pointer to the found element or NULL if it was not * found. */ static struct nlist* lookup(char* s) { // cerr << "lookup(" << s << ") called." << endl; struct nlist* np; for (np = hashtab[hash(s)]; np != NULL; np = np->next) if (strcmp(s, np->name) == 0) return np; /* found */ return NULL; /* not found */ } /* install: put name in hashtab. * * returns a pointer to the new element if all went well, * returns NULL on error. */ static struct nlist *install(char* name) { // cerr << "install(" << name << ") called." << endl; struct nlist* np; unsigned hashval; if ((np = lookup(name)) == NULL) { /* not found */ np = (struct nlist*) malloc(sizeof(*np)); if (np == NULL || (np->name = strdup(name)) == NULL) return NULL; hashval = hash(name); np->next = hashtab[hashval]; hashtab[hashval] = np; } return np; } /* attibute_to_string - * turn an attribute into a string * * idea: call print() with a strstream */ static char* attribute_to_string( Attribute* a ) { strstream printstream; Latex_cweb_output o(printstream); a->print(o); return printstream.str(); } /* forward declaration of debugging function */ static void debug_print( char* this_is, Attribute* stuff ); %} %% // inserting $s for TeX's math mode is quite tricky because // at the beginning of \LA and \RA noweb expects to not be in // math mode and complains about missing $s when we're already in // it. Solution: We'll use Lee's \mathin and \mathout macros to // surround expressions and alike. It's better to selectively invoke // math mode than have everything in it. final : exp { "\\mathin" $1 "\\mathout" } // [ debug_print("Final exp", $1); ] | stmt { $1 } // [ debug_print("Final stmt", $1); ] | error { "syntax error" } ; // get formatting of identifiers right id : ID { [ lookup(attribute_to_string($1)) ? create("{\\bf ") : create("{\\it ") ] $1 "}" } ; // ************************************************************ // format expressions: exp : NUMBER | STRING ; // easy things: // I don't know why I have duplicated everything (exp, id) but // I think it was in order for typedef to work correctly exp : exp UNOP // x++ | id UNOP | UNOP exp // ++x | UNOP id | exp BINOP exp | id BINOP exp | exp BINOP id | id BINOP id | exp UNORBINOP exp | id UNORBINOP exp | exp UNORBINOP id | id UNORBINOP id | UNORBINOP exp // *x | UNORBINOP id | LPAR exp RPAR // (x+1) | LPAR id RPAR | id LBRACK exp RBRACK // a[10] | id LBRACK id RBRACK // a[i] | id LBRACK RBRACK { $1 $2 "\\," $3 } // a[] | id LPAR decl_list RPAR { "\\hbox{" $1 $2 $3 $4 "}" } // f(x+1) f(a,b) | id LPAR RPAR { "\\hbox{" $1 $2 "\\," $3 "}" } // f() ; // ************************************************************** // declarations of variables with or without initializers decl : INT_LIKE decl_list { $1 "\\ " $2 } // int a, b, c | INT_LIKE INT_LIKE decl_list { $1 "\\ " $2 "\\ " $3 } // extern int a | id decl_list { $1 "\\ " $2 } // foo bar ; // lists like in function headings, i.e. f(int i, int b) params_list : decl | decl COMMA params_list { $1 $2 opt9 "\\ " $3 } ; // a sequence of variables (possibly with initializers) decl_like : exp { "\\mathin " $1 "\\mathout " } | id // i ; decl_list : decl_like | decl_like COMMA decl_list { $1 $2 opt9 $3 } ; stmt : decl SEMI // int i; ; // *************************************************************** // typedefs. it's important that the identifier is an ID token and // not an id token (which has italics around it already) typedef : TYPEDEF_LIKE INT_LIKE ID [ install(attribute_to_string($3)); ] { $1 "\\ " $2 "\\ {\\bf " $3 "}" } | TYPEDEF_LIKE INT_LIKE UNORBINOP ID // typedef char* String [ install(attribute_to_string($4)); ] { $1 "\\ " $2 $3 "\\ {\\bf " $4 "}" } ; stmt : typedef SEMI ; // *************************************************************** // statements stmt : exp SEMI { "\\mathin " $1 "\\mathout " $2 } ; // empty block stmt : LBRACE RBRACE { $1 "\\," $2 } | SEMI ; // block statement stmt : LBRACE stmt RBRACE { force $1 indent force $2 outdent force $3 force } ; // ***************************************************************** // control structures // if then / if then else / while / case stmt : IF_LIKE exp stmt { $1 "\\ \\mathin " $2 "\\mathout\\ " $3 } | IF_LIKE exp stmt ELSE_LIKE stmt { $1 "\\ \\mathin " $2 "\\mathout\\ " $3 "\\ " break_space $4 "\\ " $5 } ; // for loops stmt : IF_LIKE LPAR stmt stmt exp RPAR stmt // for (i=1;i<1;i++); { $1 "\\ \\mathin " $2 $3 "\\ " $4 "\\ " $5 $6 "\\mathout\\ " $7 } | IF_LIKE LPAR stmt stmt RPAR stmt // for (;;); { $1 "\\ \\mathin " $2 $3 "\\ " $4 $5 "\\mathout\\ " $6 } ; // do, case etc stmt : DO_LIKE stmt IF_LIKE exp SEMI { $1 $2 $3 "\\ \\mathin " $4 "\\mathout " $5 } | CASE_LIKE SEMI // return; | CASE_LIKE exp SEMI { $1 "\\ \\mathin " $2 "\\mathout " $3 } ; tag : CASE_LIKE COLON // default: | id COLON { "\n@def " $1 "\n" "\\mathin " $1 "\\mathout " $2 } | CASE_LIKE exp COLON { $1 "\\ \\mathin " $2 "\\mathout " $3 } | tag tag { $1 break_space $2 } // 1: 2: ; stmt : tag stmt { force backup $1 "\\ " opt9 $2 } // 1: a=1; ; // join up statements stmt : stmt stmt { $1 force $2 } | stmt SEMI // empty statemet ; // *********************************************************** // preprocessor directives stmt : LPROC | LPROC stmt | LPROC STRING // #include "abc.h" | LPROC LPROC // #include | INSERT ; // ********************************************************* // do nothing rules for comments and ignores ... %% static void debug_print( char* this_is, Attribute* stuff ) { cerr << "*** " << this_is << ":" << endl; Latex_cweb_output os(cerr); stuff->print(os); } /* * $Log: cee.fg,v $ * Revision 1.3 1996/12/16 19:28:54 gaertner * c without noweb * * Revision 1.2 1996/12/16 19:02:09 gaertner * release version * * Revision 1.1 1996/12/11 17:14:16 gaertner * Initial revision * */ pretzel-2.0n-2/languages/cee/index.list0000644000000000000000000000047106360713170016566 0ustar rootrootthis directory & a Pretzel input for prettyprinting simple C Makefile & the Makefile cee.fg & Pretzel input files cee.ft & complex-example.c & a complex example for testing example.c & a more simple example for testing fullexample.ps & output produced by a test run fullexample.tex & frame of prettyprinted code pretzel-2.0n-2/languages/cee/index.html0000644000000000000000000000226306360713177016567 0ustar rootroot Index file for directory "pretzel/languages/cee" of Pretzel distribution

Index file for directory "pretzel/languages/cee" of Pretzel distribution

Files and directories are:

this directory

    a Pretzel input for prettyprinting simple C
Makefile
    the Makefile
cee.fg
    Pretzel input files
cee.ft
complex-example.c
    a complex example for testing
example.c
    a more simple example for testing
fullexample.ps
    output produced by a test run
fullexample.tex
    frame of prettyprinted code

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:47:44 MESZ 1997 pretzel-2.0n-2/languages/cee/Makefile0000644000000000000000000000071406255447764016242 0ustar rootroot test: pretzel-it cee ceepp ceepp example.tex tex-it latex fullexample.tex complextest: pretzel-it cee ceepp ceepp example.tex tex-it latex fullexample.tex fullexample.ps: fullexample.dvi dvips -o fullexample.ps fullexample.dvi # make object code for noweb filter objects: pretzel-it -i cee ceepp clean: rm -f *.log *.dvi *.o *.toc *.aux *.o *.l *.y rm -f ptokdefs.h cee.tab.c cee.lex.c cee.lex.o cee.tab.o pretzel-2.0n-2/languages/cee/example.c0000644000000000000000000000003006255447604016361 0ustar rootroot int i; a=b; a->c = 1; pretzel-2.0n-2/languages/cplusplus/0000755000000000000000000000000006360713310016052 5ustar rootrootpretzel-2.0n-2/languages/cplusplus/cplusplus.fg0000644000000000000000000003735206255451743020450 0ustar rootroot/* a first go at a pretzel formatted grammar for C++ * * by Felix Gaertner * * $Id$ * * taken from the file headerparse.y by Karel Zuiderveld * */ %token CLASS BASENAME EXPLICIT %token TEMPLATE PUBLIC PRIVATE PROTECTED %token CONST ENUM CSCOPE STRUCT UNION SIZEOF %token VIRTUAL OPERATOR NO_WRAPPER NO_PARSE %token INLINE FRIEND TYPEDEF IMPLEMENTATION DESCRIPTION DEPENDENCY %token MUTABLE NUL COLON %token PLUS PLUS_EQUAL PLUS_PLUS %token MINUS MINUS_EQUAL MINUS_MINUS %token MULT MULT_EQUAL END_OF_DATA %token DIV DIV_EQUAL NOT NOT_EQUAL EXTERN CXXSCOPE %token LEFT_SHIFT RIGHT_SHIFT SMALLER LARGER %token EQUAL EQUAL_EQUAL CURLY_CLOSE STATIC %token SEMICOLON CURLY_OPEN %token PREPROC_LINE PREPROC_INCLUDE PREPROC_IF PREPROC_ELSE %token PREPROC_ELIF PREPROC_ENDIF PREPROC_ASSERT PREPROC_DEFINE %token PREPROC_UNDEF PREPROC_ERROR PREPROC_IFDEF PREPROC_PRAGMA %token ID TEMPLATE_ID COMMENT CHAPTER NUMBER CHAR_CONST %token STRING TYPE PT_FUNC CONCAT_STRING TEMPLATE_SPEC %type basic_type type stars operator function_default %type varcomment dc arraydef const_expression variable_argument %type var_func_name simple_const_expression %type grouped_simple_const_expression classdef %type variablename argument initvalue simple_initvalue %type initvalue_list initvalues type_prefix type_scope type_mod %type initstatements initlist %type variable_modifier simple_type template_intro %type template_intro_id_list %type source_select constructed_type preproc_global preproc_ifelse %type nameless_arg_list nameless_arg %type nameless_type variable_init_value template_id_list %type variable %type function_prelud tfn_prelud %type instantiate_function_prelud %type func_braces inline_func_def %% /* A program is a sequence of definitions */ program: /* nothing */ | definition program ; preproc_ifelse: PREPROC_IF | PREPROC_ELSE | PREPROC_ELIF | PREPROC_ENDIF | PREPROC_IFDEF ; preproc_global: PREPROC_LINE | PREPROC_INCLUDE | PREPROC_ASSERT | PREPROC_DEFINE | PREPROC_UNDEF | PREPROC_ERROR | PREPROC_PRAGMA ; preproc: preproc_global | preproc_ifelse ; // The following is a list of everything that can be found on a global // level. definition: classdecl // A class declaration | globalenumdef // An enum defintion */ | var_def // Global variables definitions */ | var_func_def // Global variables or functions def */ | typedef // A hack for typedefs */ | source_change // Change output file */ | preproc // preprocessor literals */ | COMMENT // Unbound C++ comment. Just ignore. // Doesn't belong here in | CHAPTER // Unbound C++ comment. A warning is // in place. A possible CHAPTER that // is unbound may be caused by the // fact that the user inserted inline // functions between the classdef and // the documentation. Just ignore. // Doesn't belong here in the first // place :-( | CSCOPE CURLY_OPEN // extern "C" | CURLY_CLOSE // probably from extern "C" ; source_select: STRING | BASENAME STRING | DEPENDENCY | IMPLEMENTATION | DESCRIPTION | END_OF_DATA ; source_options: /* empty */ | ',' NO_WRAPPER source_options | ',' NO_PARSE source_options ; source_change: '[' '[' source_select source_options ']' ']' ; typedef: TYPEDEF SEMICOLON varcomment ; member_typedef: TYPEDEF SEMICOLON varcomment ; enumarg: ID EQUAL NUMBER varcomment | ID EQUAL '(' NUMBER ')' varcomment | ID EQUAL MINUS NUMBER varcomment | ID EQUAL '(' MINUS NUMBER ')' varcomment | ID EQUAL NUL varcomment | ID varcomment ; enumlist: enumarg | enumarg ',' varcomment enumlist | preproc_ifelse | preproc_ifelse enumlist ; globalenumdef: ENUM ID varcomment CURLY_OPEN enumlist CURLY_CLOSE SEMICOLON varcomment | ENUM varcomment CURLY_OPEN enumlist CURLY_CLOSE SEMICOLON varcomment ; memberenumdef: ENUM ID varcomment CURLY_OPEN enumlist CURLY_CLOSE SEMICOLON varcomment | ENUM varcomment CURLY_OPEN enumlist CURLY_CLOSE SEMICOLON varcomment ; func_braces: varcomment CURLY_OPEN CURLY_CLOSE ; inline_func_def: func_braces | func_braces SEMICOLON ; chapters: CHAPTER varcomment chapters | varcomment ; simplemember: membervariable | memberfunction | simple_union_struct_def | preproc_ifelse ; class_save: ; simplemembers: simplemember | simplemember simplemembers ; simple_union_struct_def: simple_id simplemembers CURLY_CLOSE ID SEMICOLON varcomment class_save | simple_id simplemembers CURLY_CLOSE SEMICOLON varcomment class_save ; simple_id: STRUCT CURLY_OPEN | STRUCT ID CURLY_OPEN | UNION CURLY_OPEN | UNION ID CURLY_OPEN ; classdef: CLASS ID | STRUCT ID | UNION ID | UNION ; friend_defs: FRIEND ID SEMICOLON varcomment | FRIEND CLASS ID SEMICOLON varcomment | FRIEND CLASS ID template_id_list SEMICOLON varcomment ; classdecl: classdef inheretance classdescription CURLY_OPEN classdefinition CURLY_CLOSE SEMICOLON chapters class_save | classdef SEMICOLON varcomment // forward declraration | template_intro classdef inheretance classdescription CURLY_OPEN classdefinition CURLY_CLOSE SEMICOLON chapters class_save | template_intro classdef SEMICOLON ; simple_const_expression: NUMBER | MINUS NUMBER | PLUS NUMBER | NUL | ID | ID '(' initvalue_list ')' | '&' ID | MINUS ID | PLUS ID | SIZEOF '(' simple_type ')' ; grouped_simple_const_expression: simple_const_expression | '(' simple_const_expression ')' ; const_expression: grouped_simple_const_expression | grouped_simple_const_expression PLUS grouped_simple_const_expression | grouped_simple_const_expression MINUS grouped_simple_const_expression | grouped_simple_const_expression MULT grouped_simple_const_expression | grouped_simple_const_expression LEFT_SHIFT NUMBER | grouped_simple_const_expression RIGHT_SHIFT NUMBER ; arraydef: /* NOTHING */ | '[' ']' arraydef | '[' const_expression ']' arraydef ; variablename: ID | ID COLON NUMBER | '(' stars ID ')' '(' optional_function_args ')' ; optional_function_args: function_args | /* nothing */ ; variable: type variablename arraydef ; membervariable: variable SEMICOLON varcomment ; dc: COMMENT | COMMENT dc ; varcomment: /* NOTHING */ | dc ; var_func_open: regular_func | template_func_def | template_specialisation ; regular_var_func_prelud: type function_prelud | function_prelud ; template_var_func_prelud: type tfn_prelud | tfn_prelud | type OPERATOR operator '(' // This is a global // operator, not part // of a class | type ID '(' // This is a global // function (non // class) prelud ; template_instantiate_prelud: type instantiate_function_prelud | instantiate_function_prelud ; regular_func: regular_var_func_prelud // Suppress possible warnings about missing arguments in case of // the function definition. Missing arguments in that case are no // problem. In some case this is even needed to suppress warnings // from the C++ compiler | INLINE regular_var_func_prelud // Suppress possible warnings about missing arguments in case of // the function definition. Missing arguments in that case are no // problem. In some case this is even needed to suppress warnings // from the C++ compiler ; template_func_def: template_intro template_var_func_prelud | template_intro INLINE template_var_func_prelud ; template_specialisation: template_instantiate_prelud | INLINE template_instantiate_prelud ; var_func_def: var_func_open function_tail varcomment func_braces // If the function found has a parent, we must locate the function // in parent. We then add the definition to the already existing // definition and remove the build function so far. There is one // exception. If the just found function is a specialization, we // must add it as a new function to the class // or t'is standalone function. This function must be registered, // so that the data can eventually can be removed | var_func_open function_args function_tail varcomment func_braces // If the function found has a parent, we must locate the function // in parent. We then add the definition to the already existing // definition and remove the build function so far. There is one // exception. If the just found function is a specialization, we // must add it as a new function to the class. Possible function // comment is ignored // or t'is standalone function. This function must be registered, // so that the data can eventually can be removed | var_func_open ')' SEMICOLON varcomment | var_func_open function_args ')' SEMICOLON varcomment // In the var_func_prelud part of the parser, we assumed we found a // function. Since a variable with arguments is so close to a // function definition we "abuse" the FunctionStore type to store // this variable in. | var_func_open initvalue_list ')' SEMICOLON varcomment // In the var_func_prelud part of the parser, we assumed we found a // function. Ignore this function def and create a variable. Store // the variable in the output file ; template_intro_id_list: CLASS ID | CLASS ID ',' template_intro_id_list ; template_intro: TEMPLATE SMALLER template_intro_id_list LARGER ; instantiate_function_prelud: ID template_id_list CXXSCOPE ID '(' // Specialization of template. Example: // RGBColor Interpolation::akima(...){} ; template_id_list: SMALLER ID TEMPLATE_SPEC LARGER | TEMPLATE_SPEC ; tfn_prelud: ID template_id_list CXXSCOPE ID '(' // Example: // RGBColor Interpolation::akima(...){} // ~~~~~~~~~~~~~~~~~~~~~~~~ | ID template_id_list CXXSCOPE ID CXXSCOPE ID '(' // Nested class definition // Example: // type Interpolation::netstedclass::name() {} | ID template_id_list CXXSCOPE ID CXXSCOPE OPERATOR operator '(' // Nested class definition | ID template_id_list CXXSCOPE OPERATOR operator '(' | ID template_id_list CXXSCOPE OPERATOR type '(' ; function_prelud: ID CXXSCOPE ID '(' | ID CXXSCOPE OPERATOR operator '(' | ID CXXSCOPE OPERATOR type '(' | ID '(' // This is either a global function prelud or a variable prelud. // For the moment we just assume it is a function and later on, we // may ignore the function later on if it is a variable after all. | OPERATOR operator '(' // This is a global operator, not part of a class ; variable_init_value: ; // ------------------------------------------------------- // var_def: Variable definitions var_def: type var_func_name arraydef SEMICOLON varcomment | type var_func_name EQUAL variable_init_value SEMICOLON varcomment | type var_func_name '[' ']' EQUAL variable_init_value SEMICOLON varcomment | type '(' stars var_func_name ')' '(' ')' EQUAL variable_init_value SEMICOLON varcomment | type '(' stars var_func_name ')' '(' function_args ')' EQUAL variable_init_value SEMICOLON varcomment ; var_func_name: ID | ID CXXSCOPE ID | OPERATOR operator ; classdef_member: classmember | classmember classdef_member ; classdefinition: classdef_member | /* nothing */ ; classmember: classdecl | member_typedef | membervariable | simple_union_struct_def | friend_defs | memberfunction | memberenumdef | PRIVATE COLON | PUBLIC COLON | PROTECTED COLON | SEMICOLON | preproc_ifelse ; operator: EQUAL | NOT | PLUS | MINUS | MULT | '~' | DIV | SMALLER | LARGER | '^' | '|' | '&' | '[' ']' | LEFT_SHIFT // << | RIGHT_SHIFT // >> | EQUAL_EQUAL // == | NOT_EQUAL // != | PLUS_EQUAL // += | MULT_EQUAL // *= | DIV_EQUAL // /= | MINUS_EQUAL // -= | PLUS_PLUS // ++ | MINUS_MINUS // -- | '(' ')' // () ; variable_modifier: stars | '&' | /* empty */ ; variable_argument: variable_modifier ID | variable_modifier ID '.' variable_argument | variable_modifier ID CXXSCOPE ID | variable_modifier ID '(' ')' | variable_modifier ID '(' initvalue_list ')' | variable_modifier ID CXXSCOPE ID '(' ')' | variable_modifier ID CXXSCOPE ID '(' initvalue_list ')' | variable_modifier ID '[' const_expression ']' ; simple_initvalue: variable_argument | NUMBER | MINUS NUMBER | NUL | STRING | CONCAT_STRING ; initvalue: simple_initvalue | '(' type ')' simple_initvalue ; initvalues: initvalue | initvalue PLUS initvalues | initvalue MINUS initvalues | initvalue DIV initvalues | initvalue MULT initvalues ; initvalue_list: initvalues | initvalues ',' initvalue_list ; initstatements: ; initlist: COLON initstatements ; function_tail: ')' initlist | ')' | ')' initlist CONST | ')' CONST | ')' CONST EQUAL NUL | ')' EQUAL NUL ; memberfunction_open: memberfunction_prelud | FRIEND memberfunction_prelud | INLINE memberfunction_prelud | VIRTUAL memberfunction_prelud ; memberfunction_prelud: type ID '(' | EXPLICIT ID '(' | ID '(' | type PT_FUNC '(' | type OPERATOR operator '(' // The operators '++' and '--' are odd kind of operators that may // require an optional argument without variable name. Suppress // possible warnings in the case that the operator is '++' or // '--'. | OPERATOR type '(' ; memberfunction: memberfunction_open function_tail SEMICOLON varcomment | memberfunction_open function_args function_tail SEMICOLON varcomment | memberfunction_open function_args function_tail inline_func_def varcomment | memberfunction_open function_tail inline_func_def varcomment ; function_default: NUL | STRING | '\"' '\"' | '(' NUL ')' | NUMBER | '(' NUMBER ')' | CHAR_CONST | '(' CHAR_CONST ')' | ID | MINUS ID | MINUS NUMBER | '(' ID ')' | ID CXXSCOPE ID | '(' ID CXXSCOPE ID ')' | '&' ID | '(' '&' ID ')' ; argument: type | type CXXSCOPE type | type CXXSCOPE type variablename arraydef | type variablename arraydef | type PT_FUNC '(' ')' | type PT_FUNC '(' nameless_arg_list ')' ; function_arg: argument | argument EQUAL function_default | '.' '.' '.' ; nameless_type: type | type variablename arraydef | type PT_FUNC '(' ')' | type PT_FUNC '(' nameless_arg_list ')' ; nameless_arg: nameless_type | nameless_type EQUAL function_default | '.' '.' '.' ; function_args: function_arg | function_arg ',' function_args ; nameless_arg_list: nameless_arg | nameless_arg ',' nameless_arg_list ; stars: MULT | MULT stars ; simple_type: TYPE | TEMPLATE TYPE | ID | ID CXXSCOPE ID | ID '[' const_expression ']' ; type_scope: STATIC | EXTERN | CSCOPE ; type_mod: CONST | MUTABLE ; type_prefix: type_scope type_mod | type_mod | type_scope ; basic_type: TYPE | ID | TEMPLATE_ID | ENUM ID | STRUCT ID | ID CXXSCOPE ID | TEMPLATE TYPE | ID template_id_list | ID SMALLER ID LARGER CXXSCOPE ID // Really a hack for nested definitions. Need some something // dynamic one day | ID SMALLER ID LARGER CXXSCOPE TYPE // Really a hack for nested definitions. Need some something // dynamic one day | ID SMALLER basic_type stars LARGER | ID SMALLER basic_type LARGER | ID SMALLER basic_type '&' LARGER | ID SMALLER basic_type ',' basic_type LARGER | ID SMALLER basic_type ',' basic_type stars LARGER | ID SMALLER basic_type ',' basic_type '&' LARGER | ID SMALLER basic_type stars ',' basic_type LARGER | ID SMALLER basic_type stars ',' basic_type stars LARGER | ID SMALLER basic_type stars ',' basic_type '&' LARGER ; constructed_type: basic_type | basic_type stars | basic_type stars '&' | basic_type stars CONST | basic_type '&' ; type: constructed_type | type_prefix constructed_type ; classdescription: varcomment ; inheretance: /* empty string */ | COLON inheretancelist ; inheretancemember: PUBLIC ID | PRIVATE ID | PROTECTED ID | PUBLIC ID template_id_list | PRIVATE ID template_id_list | PROTECTED ID template_id_list | PUBLIC ID SMALLER type LARGER | PRIVATE ID SMALLER type LARGER | PROTECTED ID SMALLER type LARGER ; inheretancelist: inheretancemember | inheretancemember ',' inheretancelist ; %% pretzel-2.0n-2/languages/cplusplus/index.list0000644000000000000000000000022406360713302020055 0ustar rootrootthis directory & a first go at a Pretzel prettyprinter for C++ README & more information cplusplus.fg & a first try at a Pretzel formatted grammar pretzel-2.0n-2/languages/cplusplus/README0000644000000000000000000000025106255452026016737 0ustar rootrootREADME for the languages/cplusplus subdirectory of Pretzel This is a fist go at C++. I haven't continued this path because I wanted to finish a C prettyprinter first. pretzel-2.0n-2/languages/cplusplus/index.html0000644000000000000000000000157506360713310020057 0ustar rootroot Index file for directory "pretzel/languages/cplusplus" of Pretzel distribution

Index file for directory "pretzel/languages/cplusplus" of Pretzel distribution

Files and directories are:

this directory

    a first go at a Pretzel prettyprinter for C++
README
    more information
cplusplus.fg
    a first try at a Pretzel formatted grammar

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 15:48:57 MESZ 1997 pretzel-2.0n-2/README0000644000000000000000000002032406651063176012746 0ustar rootroot $Id: README,v 2.3 1998/02/24 15:38:55 gaertner Exp $ README for Pretzel v.2.0n What's new from v.2.0i? ======================= o major bug fix with noweb prettyprinting filter (now you can use plain old noweb verbatim by default) o major bug fix (suggested by David Wilson) in fgparse.nw o enhanced compatibility to debian linux (thanks to Anthony Towns) o added a prettyprinter for guarded command language (by Anthony Towns) in contrib/aj What's new from v.2.0f? ======================= o minor bug fix (due to Holger Uhr) o full featured Java prettyprinter for use with noweb included o updated PretzelBook (now second edition) and documentation What's new from v.2.0h? ======================= o noweb prettyprinters are more robust in that they use the standard noweb verbatim environment in case prettyprinting doesn't work Introduction: ============= This is the README to the pretzel system distribution v.2.0m. Pretzel is a tool that helps you to generate arbitrary prettyprinters for any language or formatter you like. In this release, Pretzel offers enhanced support for Norman Ramsey's noweb literate programming tool. Pretzel adds fully user controlled prettyprinting and indexing facilities to noweb and thus eliminates a lot of deficits of noweb, which is in nature a language independent tool. Pretzel comes with ready to use prettyprinters for Pascal and Java (contributed by Lee Wittenberg). A rudimentary prettyprinter for C is also included. Prettyprinters for other languages may be written within hours (or days, as for C :-). The distribution is fully documented using noweb and contains quick reference manual pages as well as a full blown user manual, the PretzelBook. Prerequisites: ============== You'll need up-to-date executable versions of: o the noweb literate programming system [ftp: host: ftp.th-darmstadt.de, dir: /pub/programming/literate-programming/independent] o flex, the fast lexical analyser generator [at least version 2.4.6] o Bison, the GNU Parser generator [at least version 1.19] o The GNU g++ compiler (or any other C++ compiler at hand). Obtaining Pretzel: ================== Pretzel may be obtained through the Internet at the following URL: http://www.informatik.tu-darmstadt.de/BS/Gaertner/pretzel/code/pretzel-2.0m.tar.gz There also is the Pretzel homepage that always contains the latest information on the system: http://www.iti.informatik.th-darmstadt.de/~gaertner/pretzel You may also browse the distribution to get individual files at: http://www.informatik.tu-darmstadt.de/BS/Gaertner/pretzel/distribution/ Installation & Getting Started: =============================== 1. To get an executable version of pretzel, unpack the distribution and read the README (this file fully). 2. Edit the beginning of the global Makefile to suit your system (i.e. specify where the executables, libraries, etc. should go). 3. Type: make This will make the executables, objects and libraries for your system. 4. Type: make install This will copy the installation files to the right places on your system. 5. Setup environment variables PRETZEL_LIBDIR and PRETZEL_INCLUDE to point to the directory with the library and the directory with the includes. Now you are ready to build prettyprinters of your own. Try copying the pascal.ft and pascal.fg files (from the languages/pascal subdirectory) into a directory of their own. Then type pretzel-it pascal pascalpp This will produce a pascal prettyprinter executable pascalpp, which reads pascal text from stdin and writes prettyprinted text in LaTeX to stdout. In your LaTeX documents, include the document style option `pretzel-latex' and you have a new environment `ppcode' into which the text from pascalpp may be included. Documentation: ============== The user manual of Pretzel is called the Pretzelbook. It can be found in the Pretzel distribution in the doc/pretzelbook directory. It is the ultimate source of information on Pretzel and its friends. Pretzel and noweb: ================== Pretzel comes with a facility to build prettyprinting filters for noweb. See the Pretzelbook and/or the directory contrib/noweb for more information. The directory contrib/leew contains Lee Wittenbergs prettyprinting filter for Java. All directories contain README files that you may consult for more information. Files: ====== Here's an overview over the directory structure: README this file diary the diary of pretzel doc documentation doc/pretzelbook the Pretzelbook doc/styles LaTeX styles for prettyprinting man manpages attr the Attribute class output the Output class ftokens the prettyprinting scanner generator fgrammar the prettyprinter generator function main main pretzel program pretzel-it directory for pretzel-it shell script languages contains examples for several languages languages/pascal Pretzel input for Pascal languages/cee Pretzel input for C (experimental) bin directory for pretzel executables contrib/noweb noweb prettyprinting ad-on contrib/noweb/general general stuff for noweb prettyprinters contrib/noweb/cee.latex noweb prettyprinter for C and LaTeX contrib/noweb/cee.html noweb prettyprinter for C and HTML (experimental) contrib/leew Lee Wittenberg's noweb prettyprinter for Java Thanks: ======= I have to thank firstly Joachim Schrod for initiating this project and his encouragement to hang on to it for so long. I also have to thank Lee Wittenberg and Norman Ramsey for their help on release 2.0. Thanks also to Roger Kehr and all those other students whom I have discussed this topic with (whether they wanted or not). I am very grateful to the Institut f"ur Theoretische Informatik here in Darmstadt and to Professor Waldschmidt for providing the computing resources for this project. Release 2.0 comes as a christmas present for me and the people on the USENET comp.programming.literate newsgroup, who -- with their discussions -- have helped to improve my understanding of this subject and --- with their citations --- also have helped to impove the Pretzelbook. :-) Author: ======= Send comments and bug reports to Felix Gaertner at fcg@acm.org or snail mail to: Felix Gaertner Sonnhalde 9 D-35041 Marburg Germany =================================================================== This is Pretzel v.2.0, the language independent prettyprinter generator. Copyright (C) 1995-98 by Felix Gaertner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA =================================================================== $Log: README,v $ Revision 2.3 1998/02/24 15:38:55 gaertner for Version 2.0i Revision 2.2 1997/07/09 14:34:16 gaertner for version 2.0g Revision 2.1 1996/12/17 08:19:18 gaertner added acknowledgements Revision 2.0 1996/12/16 18:05:38 gaertner for release 2.0f Revision 1.8 1995/09/08 16:18:09 gaertner *** empty log message *** Revision 1.7 1995/09/07 17:43:39 gaertner Adapted to new Makefile. Revision 1.6 1995/09/05 16:44:58 gaertner Removed section on multiple prettyprinters. Inserted pointers to ADDENDUM. Revision 1.5 1995/08/29 17:43:37 gaertner Added section on multiple prettyprinters. Revision 1.4 1995/07/20 09:28:10 gaertner Added note to pretzel-it script. Simplified installation documentation. Revision 1.3 1995/04/27 07:51:09 gaertner Added Gnu General Public License heading. Revision 1.2 1995/04/26 17:03:35 gaertner Updated entries to suit new global Makefile. Revision 1.1 1995/04/26 16:03:47 gaertner Initial revision pretzel-2.0n-2/htmlify0000755000000000000000000000225706360634111013463 0ustar rootroot#! /usr/local/bin/bash #set -x usage='usage: htmlify' # dirname=`pwd` # /a/spelunke/export/vol1 dirname=`expr ${dirname} : '/a/spelunke/export/vol1/gaertner/\(.*\)'` input="index.list" output="index.html" # if [ $# -gt 0 ] then echo $usage >&2 exit 1 fi umask 0 rm -f ${output}.tmp echo "Outputting to ${output}.tmp" >&2 cat > ${output}.tmp << EOD Index file for directory "DIR" of Pretzel distribution

Index file for directory "DIR" of Pretzel distribution

Files and directories are:

EOD awk 'BEGIN { FS="&" } { print "" $1 "

    " $2"
" }' ${input} >> ${output}.tmp cat >> ${output}.tmp << EOD
Felix Gaertner

To Pretzel Homepage.

Last modified: LASTMOD EOD echo "purging to " ${output} >&2 sed -e "s%DIR%${dirname}%" -e "s/LASTMOD/`date`/" ${output}.tmp > ${output} rm ${output}.tmp echo "done." >&2 pretzel-2.0n-2/doc/0000755000000000000000000000000006360650776012637 5ustar rootrootpretzel-2.0n-2/doc/pretzelbook/0000755000000000000000000000000010765024735015171 5ustar rootrootpretzel-2.0n-2/doc/pretzelbook/pretzelbook.tex0000644000000000000000000047554710765024734020300 0ustar rootroot% $Id: pretzelbook.tex,v 2.1 1997/07/09 14:39:29 gaertner Exp $ %---------------------------------------------------------------------- % % The Pretzelbook -- the user's manual for Pretzel v.2.0 % % [LaTeX] % (history at end) % % NB: This file inputs small pretzel examples files that normally % reside in the languages/examples subdirectory of the distribution. % These files are: % % simpas.ft % simpas.fg % small-example.simpas % example-frame.tex % % \documentclass{book} \usepackage{pretzeldoc} \usepackage{a4} %\usepackage[german]{babel} \usepackage{makeidx} \makeindex % % Indexing: % \index{first key!second key!third key} % \index{sorted by@{\it looks like}} % \begin{document} \title{The PretzelBook \\ {\normalsize second edition}} \author{Felix G\"artner} \maketitle \tableofcontents % ###################################################################### \chapter{Introduction} \begin{quote} ``I do think however that it is important that you are given some control over the basic prettyprinting style, as it can get very frustrating to see your code systematically reformatted in a style that you dislike.'' Marc van Leeuwen \cite{vanLeeuwen96:pp:control} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \section{Do Prettyprinting the \pretzel{} Way} \subsubsection*{What is \pretzel{}?} Welcome to \pretzel{}. \pretzel{} is a prettyprinter generator, i.e.~a system hat builds prettyprinters. The good thing about \pretzel{} is that it builds prettyprinters with full user control. The new thing about \pretzel{} is that it doesn't build standalone prettyprinting programs, but rather builds modules that can be turned into standalone programs easiliy, but can also be incorporated into your own software systems. \index{prettyprinter!generator} \index{user control!full} \index{modules} \index{prettyprinting!modules} \subsubsection*{What is this book about?} This book is the ultimate source of information about \pretzel{}. It explains nearly all (known and unknown) facets of the \pretzel{} system and should be usefull to anybody using the system. \index{ultimate source} \index{pretzel@\pretzel{}!ultimate source} \subsubsection*{How should I read this book?} First of all, I expect that you are aquainted with the issue of prettyprinting. Why would you use a system like \pretzel{} if you weren't?! (However, if you want to freshen up your understanding of the subject matter, you should have a glance at chapter \ref{chap:on:prettyprinting} at some pleasing time, which gives an overview over the area of prettyprinting and the history of the concepts behind it.) Essentially, you should start with the first chapter, that is the tutorial of \pretzel{}. This might be the only part of this document that most people will read. Later chapters deal with the more intricate parts of using \pretzel{} (like chapter \ref{chap:pretzel:hacking}, ``\pretzel{} hacking'') or with combining \pretzel{} with the popular programming tool \noweb{} (chapter \ref{chap:pretzel:meets:noweb}, ``\pretzel{} meets \noweb{}''). The final chapter is the reference manual of \pretzel{}. Consult this section only in emergencies. \subsubsection*{Where can I get \pretzel{}?} You can probably get \pretzel{} through the site or person through which you got this document. \pretzel{} is free software, i.e.~you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (either version 2 of the License, or (at your option) any later version). \index{pretzel@\pretzel{}!obtaining} \index{GNU General Public License} \index{Free Software Foundation} You can get the latest version of the distribution by looking at the following WWW address, which points to the \pretzel{} homepage: % \index{homepage!Pretzel} \index{Pretzel!homepage} % \begin{center} \verb"http://www.iti.informatik.th-darmstadt.de/~gaertner/pretzel/" \end{center} The latest distribution resides at: % \begin{center} \verb"http://www.iti.informatik.th-darmstadt.de/~gaertner/pretzel/code/" \end{center} % The current release number of \pretzel{} is 2.0. Look out for the latest information on the \pretzel{} homepage, if you want to be up to date. \index{Pretzel!currect release} \index{2.0} \index{date!up to} \subsubsection*{How do I install \pretzel{}?} The distribution contains a file called {\tt README} that contains further instructions how to install \pretzel{}. To date, \pretzel{} runs on \UNIX{}isch like machines and has been tested under HP-UX, AIX RS6000 platforms and under Linux. It uses the GNU {\tt g++} compiler and the common \UNIX{} tools {\tt flex} and {\tt Bison}. \index{readme@{\tt README}} \index{Pretzel!installing} \index{installing Pretzel} \index{UNIX} \index{HP-UX} \index{AIX} \index{RS6000} \index{GNU@GNU {\tt g++} Compiler} \index{flex} \index{Bison} \section{History} The \pretzel{} system started off as a minor project at the Institut f\"ur Theoretische Informatik at the Technical University of Darmstadt, Germany early 1993. It was revised during a sabbatical at Trinity College, Dublin in late 1993 and version 1.1 was finished back in Darmstadt in the summer of 1994. In early 1996 encouragement from the net led me to take up the project again and prepare release 2.0, which main feature was the ability to interface with \noweb{}. This release was out by christmas 1996. Work continues mostly on building new prettyprinting grammars for several languages. \index{Pretzel!history} \index{Darmstadt} \index{ITI} \index{Trinity College, Dublin} \index{Dublin} \index{noweb} \index{christmas 1996} \section{Acknowledgements} \pretzel{} is by far no finished system and a lot still needs to be done. However I have to thank firstly Joachim Schrod for initiating this project and his encouragement to hang on to it for so long. I also have to thank Lee Wittenberg and Norman Ramsey for their help on release 2.0 and to Holger Uhr for pointing me to a bug. Thanks also to Roger Kehr and all those other students whom I have discussed this topic with (whether they wanted or not). I am very grateful to the Institut f\"ur Theoretische Informatik here in Darmstadt and to Professor Waldschmidt for providing the computing resources for this project. Release 2.0 comes as a christmas present for me and the people on the {\sc USENET} {\tt comp.programming.literate} newsgroup, who --- with their discussions --- have helped to improve my understanding of this subject and --- with their citations --- also have helped to impove this book by far. \index{Schrod, Joachim} \index{Waldschmidt, Helmut} \index{Wittenberg, Lee} \index{USENET} \index{Ramsey, Norman} \index{comp@{\tt comp.programming.literate}} \index{2.0} \index{newsgroup} \index{Kehr, Roger} \index{Uhr, Holger} \index{students} \index{ITI} \section{Changes to second Edition} \label{sec:secondEdition} The second edition of the PretzelBook features a dramatically enhanced chapter on interfacing with \noweb{} and minor changes to the chapter on \pretzel{} hacking. % ###################################################################### \chapter{Using Pretzel} \label{chap:using:pretzel} \begin{quote} ``I'm using \CWEB{} to write chapters for books, and really appreciate the pretty-printing and automatic indexing and cross-referencing.'' Tim Kientzle \cite{kientzle:use:of:prettyprinting} \end{quote} \index{Kientzle, Tim} \index{CWEB} \index{indexing, automatic} \noindent This chapter explains how to use \pretzel{} in an everyday setting. It covers the things you need to know if you want to build a \pretzel{} prettyprinter from an existing set of \pretzel{} input files or if you want to modify an existing input or write a totally new one from scratch. It assumes that the \pretzel{} system has already been installed on your system so that you can invoke the \t{pretzel-it} command from your command prompt. You don't need any prior experience with \pretzel{} or \LaTeX{} to start, maybe just a slight idea of what kind of things regular expressions and context free grammars are, what prettyprinting is about and how your source code looks best in a prettyprinted way. \index{everyday setting} \index{setting, everyday} \section{Getting Started} This section will give a first introduction to using \pretzel{}. It will show how to build a prettyprinter for a simple programming language, which will be a subset of standard \PASCAL{}. After reading this section and doing the excercises, you will be able to build arbitrary prettyprinters from the ready-to-go input files included in the \pretzel{} distibution. \subsection{A first Example} The input to \pretzel{} will always be {\em two} files. Let's start with these files first and look at \pretzel{} in action. So you might startup your computer, invoke your favourite text editor and create two files called \t{simpas.ft} and \t{simpas.fg}. The suffixes \t{.ft} and \t{.fg} are the extensions that \pretzel{} expects for its input files. But before we learn about what they stand for, fill in the files with the following information:\footnote{You can spare yourself from typing the data if you look into the subdirectory \t{languages/examples} of the \pretzel{} distribution.} \index{Pretzel!input files} \index{simpas@{\tt simpas.fg}} \index{simpas@\t{simpas.ft}} \index{Pretzel!file extensions} \index{languages@\t{languages/examples}} \verbatiminput{simpas.ft} Here's the second file, which should be called \t{simpas.fg}: \verbatiminput{simpas.fg} The language that is covered by these first \pretzel{} specifications is \PASCAL{} with simple expressions of the form $a\leq b$ or $a=b$ (you can see which operators are allowed from the \t{pascal.ft} file). Also, the only statements allowed are assignments, the \res{if}-\res{then}-construct and the compound statement (i.e.~statements enclosed within \res{begin} and \res{end}). So the following (not prettyprinted) code would be valid in these terms:\footnote{Of course you can't do much with this ``language'', but remember that it's only an introductory example. Once you've understood the basics of this section it'll be easy to extend the specifications to cover all of \PASCAL{}.} \verbatiminput{small-example.simpas} \subsection{Running \pretzel{}} Now we are ready to start: Having these files in one of your directories, simply type: % \begin{verbatim} pretzel-it simpas simpaspp \end{verbatim} % \index{pretzelit@\t{pretzel-it}} % This will cause your machine to rattle and hum and if all goes well, it will return saying ``done.'' and leave an executable called \t{simpaspp}. This file is the prettyprinter for the specified language! \index{rattle and hum} \index{hum, rattle and} \index{simpaspp@\t{simpaspp}} \index{executable prettyprinter} \index{prettyprinter!executable} By default, the prettyprinter reads text from the standard input and writes formatted code to the standard output. So try to feed the small example to the program and look what it returns: % \index{standard input} \index{standard output} % \begin{verbatim} simpaspp 1$ \res{then} $i\mathrel{\tt :=}i-1$;\pretzelforce \res{if} $b\leq i$ \res{then} \pretzelindent \pretzelforce $b\mathrel{\tt :=}b+1$ \pretzeloutdent\pretzelforce\res{else} \pretzelindent $b\mathrel{\tt :=}b-1$; \pretzeloutdent \pretzelforce \end{outp} Say the user wants the first statement (an \res{else}-less \res{if}) to be prettyprinted without a forced line break behind the \res{then} keyword and the second statement (a simple \res{if}-\res{then}-\res{else}) to have a line break behind the keywords and additional indentation to the statements to enhance readability. This is hardly expressible in terms of ``formatted tokens'', because it would be necessary to go back in the output and insert a line break within material that might have already been output to the screen or to paper. To specify this distinction you have to tell the prettyprinter something about what \res{if}-\res{then}s are in difference to \res{if}-\res{then}-\res{else}s. That's where the formatted grammar comes into action. If you look at the \t{simpas.fg} example above, you'll notice two rules that handle these two different cases. Here are both rules again to look at: % should be changed if simpas.fg is altered \begin{verbatim} stmt : IF exp THEN stmt { $1 " $" $2 "$ " $3 " " indent $4 outdent } | IF exp THEN stmt ELSE stmt { $1 " $" $2 "$ " $3 indent force $4 outdent force $5 indent force $6 outdent force } ; \end{verbatim} The second line is more interesting at the moment: it means that any \t{IF} token followed by \t{exp}, \t{THEN}, \t{stmt}, \t{ELSE} and \t{stmt} tokens will be reduced again to a \t{stmt} token. The attached description in curled braces tells the prettyprinter to insert a forced line break (\fmt{force}) behind the \t{THEN} token if this rules fires. Additionally, the statement following the \t{THEN} should have a little more indentation before it (\fmt{indent}) which should be taken back afterwards (\fmt{outdent}). The same is specified for the second statement following the \t{ELSE} token. What is done here is to specify something like an attachment (or special attribute) of the token which this rule reduces to (i.e.~the \t{stmt} token on the left hand side). This attachment can use the attachments of the tokens on the right hand side by referring to the sequence number in which they appear there. This means that \t{\$1} references the attachment of the \t{IF} token, \t{\$2} the attachment of the \t{exp} token and so on. All the attachments between the curled braces are put together and form the attachment of the newly formed token (the \t{stmt} token). Apart from referring to the attributes of existing tokens, you can additionally insert special formatting instructions (like \fmt{indent}, \fmt{outdent} or \fmt{force}) and strings (like the \verb+" $"+) into the sequence as ``extra'' attachments. All these attachments together form the attribute of the new \t{stmt} token. \index{indent} \index{outdent} \index{force} \index{attachments} \index{attributes} \index{grammar rules} The special commands that have appeared above, e.g.~the \fmt{indent} or \fmt{force} commands, are called {\em format commands} or {\em formatting instructions}. Subsequently the prettyprinting method used by \pretzel{} prettyprinters is called {\em prettyprinting with format commands}. The main assumption is that we have a text formatter at hand that uses {\em control sequences} (or {\em tags}) inside the actual text body for specifying all different ways of formatting (such as fonts, indentation, spacing, alignment). Another term for this way of formatting is {\em in-text procedural markup} and systems using this technique are commonly called {\em document compilers}\footnote{Common examples of such typesetting systems are \TeX{} and the \UNIX{} tools Nroff/Troff.}. The idea behind the prettyprinting method presented here is to systematically insert special formatting instructions into the source code which are left to a typesetter to interpret. The history behind this method and the details of the algorithm are explained in the special chapter ``On Prettyprinting'' (chapter \ref{chap:on:prettyprinting}). From now on, simply think of formatting instructions as actions that will be performed on the typeset output before it appears on the screen or on paper. \index{prettyprinting!with format commands} \index{text formatter} \index{control sequences} \index{tags} \index{markup} \index{formatting} \index{tex@\TeX} \index{UNIX} \index{Nroff} \index{Troff} \index{prettyprinting!idea} \subsection{Formatting Instructions} Now, we'll have a look at the formatting instructions that \pretzel{} offers. \index{formatting instructions} \subsubsection*{Controlling Indentation} \index{controlling indentation} \index{indentation} We have met three formatting instructions already: \fmt{indent}, \fmt{outdent} and \fmt{force}. They in effect control the amount of indentation. The \fmt{indent} primitive increases the level of indentation by one unit, \fmt{outdent} does the same in a decreasing fashion. However, the new level of indentation only becomes visible after a forced line break, which corresponds to the \fmt{force} command. \index{force} \index{indent} \index{outdent} Let's look at an example. Here we have a simple \res{while} loop in \PASCAL{}. If the input sequence is % \begin{inp} while (ic) and (str\_buf\_ptr<=buf\_size) do \end{inp} % Inserting \fmt{break\_space}s before and after the ``\t{and}'' would seem to be a good solution to this line-breaking problem. But breaking the line after the ``\t{and}'', say, would result in % \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do} \end{outp} % what of course is intolerable. We want a long continuous line to be indented a little if it is broken, but the amount of indentation for the continuing line must be more as the ``normal'' indentation of controlled statements inf conditionals for example. This distinction visually separates adjacent (and indented) statements from a single statement that fills two lines. To this effect, there exists a new format command, namely the {\em optional line break} command \fmt{opt}. There are ten different \fmt{opt}s that specify the badness of a line break at the point of it's occurence. They are called \fmt{opt0}, \fmt{opt1},\dots, \fmt{opt9}. A smaller number encourages line breaking at this point more than a higher number. So \fmt{opt0} will nearly always lead to a line break whereas \fmt{opt9} leads to a line break only if there is no \fmt{opt0},\dots, \fmt{opt8} primitive somewhere near and the line {\em has} to be broken around this point.\footnote{In \TeX\ terms the digit $n$ in the name of the \fmt{opt} command specifies the penalty associated with this break point. The penalty in the default interpretation of \fmt{opt} is about $10\cdot n$.} So the \fmt{opt} command denotes an optional line break with the continuation line indented a little more with respect to the normal indentation. \index{opt} \index{format commands!opt} So in the example we therefore say: % \begin{inp} while (str\_buf[str\_buf\_ptr]<>c) and \fmt{opt4} (str\_buf\_ptr<=buf\_size) do \fmt{indent} \fmt{force} begin ...\fmt{force} end \end{inp} % depending on whether we rather liked a line break before or after the ``\t{and}''. This would then yield the correct way of formatting, as in: % \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myindent\myindent\myindent\myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do}\myoutdent\myoutdent\myforce \res{begin}\dots\myforce \res{end} \end{outp} % Note however that a \fmt{break\_space} is always a better place to break a line than an optional line break denoted by \fmt{opt}. \subsubsection*{Additional Commands} \index{format commands!additional} The list of format commands is not yet complete. There are still a few more primitives to learn, but they are not as important as the other commands that were presented up to this point. The following primitives were introduced to achieve better formatting results in special situations. \index{backup} \index{format commands!backup} The first one is called \fmt{backup} and denotes a little negative horizontal space. This command must be preceded by a \fmt{force}, because it doesn't make sense to backup within a line if it's beginning has already been output. So the two commands ``\fmt{force}, \fmt{backup}'' appearing in a row can be seen as a short form for the sequence ``\fmt{outdent}, \fmt{force}, \fmt{indent}''. The \fmt{backup} command is used in cases where statements are preceded by labels or simply where a line should stick out to the left a bit in order to emphasize it. % \index{Format commands!backup@\fmt{backup}} \index{backup@\fmt{backup}} The next additional command is called \fmt{big\_force}. As the name implies this primitive acts like a \fmt{force}, but on a bigger scale. \fmt{big\_force} not only forces a line break; it also inserts a little extra vertical space after the break. You can use the \fmt{big\_force} primitive to separate two adjacent lines that semantically do not belong together, like two function declarations. % \index{Format commands!big force@\fmt{big\_force}} \index{big force@\fmt{big\_force}} If you are trying to typeset \C\ or \CPP\ programs, you will need a feature to typeset so called preprocessor directives. These are commands beginning with a $\#$ that can influence the source code before compilation. Normally these lines appear beginning at the left margin so we want a command that can be used to typeset lines like this. This command is called \fmt{no\_indent}. It causes the {\bf current} line to be printed flushleft. So if you want to prettyprint a \C\ or \CPP\ preprocessor line, you should say % \index{c++@\CPP} \index{c@\C} \index{Preprocessor} \index{c preprocessor@\C\ preprocessor} \index{Format commands!no indent@\fmt{no\_indent}} \index{no indent@\fmt{no\_indent}} % \begin{inp} \fmt{force} \fmt{no\_indent} $\#$PREPROCESSOR\_DIRECTIVE \fmt{force} \end{inp} % and the line following this directive will be indented as much as the line before the directive. %cancel Finally the last command of the present command set is called \fmt{cancel}. To understand this command I have to mention a tricky detail of the presented algorithm that I have omitted in the intoduction of this section: There I said that format commands are simply output by the prettyprinter one by one just like strings, only that they are ``marked'' as typesetting commands. Actually the prettyprinter also does a little bit of interpretation in advance. But these exceptions from the rule can be caught in two phrases\label{two-phrases}. The first one is of global importance and the second one is related to the \fmt{cancel} command: \index{Format commands!cancel@\fmt{cancel}} \index{cancel@\fmt{cancel}} \index{Exceptions} \index{Preprocessing of format commands} \index{Tricky details} \begin{enumerate} \item A sequence of consecutive \fmt{break\_space}, \fmt{force}, and/or \fmt{big\_force} commands is replaced by a single command (the maximum of the given ones). \item The \fmt{cancel} command cancels any \fmt{break\_space}, \fmt{opt}, \fmt{force} or \fmt{big\_force} command that immediatly precede or follow it and also cancels any \fmt{backup} command that follows it. \end{enumerate} So it seems that the \fmt{cancel} command is a command that mixes everything up again after we have put everything into a neat and tidy form! But this only seems so. The interpretation done by the prettyprinter according to the two rules stated above, was introduced to be more generous and more flexible with the placement of format primitives into the source code. Because, after all, the format commands will not be inserted by hand (as the reader might think after viewing the examples given above), but they will be inserted automatically by the prettyprinter according to the prettyprinting grammar that we have been introduced to above. % \index{Flexibility} \index{Prettyprinting grammar} \index{Format commands!explained|)} \subsubsection*{Summary of Format Commands} \index{Format commands!summary} \index{Summary of format commands} Table \ref{command-table} shows a complete list of all the format command primitives introduced in this part of the book. The only command that wasn't mentioned up to now is the \fmt{null} primitive that serves as a neutral (or empty) command. Now, with the knowledge of all the intrinsic and extrinsiv features of the prettyprinting method of \pretzel{} prettyprinters, you are ready to read, write or modify prettyprinting grammars at your will. Now, you have total control over the prettyprinting style; fully user controlled prettyprinting is in your grasp. \index{Format commands!null@\fmt{null}} \index{null@\fmt{null}} \begin{figure}[htb] \begin{center} \begin{tabular}{lp{7cm}} \fmt{null} & empty command \\ \fmt{indent} & indents the next line a little more \\ \fmt{outdent} & takes back the last indentation (de-indent) \\ \fmt{force} & forces a line break \\ \fmt{break\_space} & denotes a possible space for a line break \\ \fmt{opt$\,n$}, $n \in \{0,\dots,9\}$ & denotes an optional line break with the continuation line indented a litte with respect to the normal starting position. This line break will score a penalty of $10n$.\\ \fmt{backup} & denotes a small backspace\\ \fmt{big\_force} & forces a line break and inserts a little extra space \\ \fmt{no\_indent} & causes the current line to be output flushleft\\ \fmt{cancel} & obliterates any \fmt{break\_space}, \fmt{opt}, \fmt{force} or \fmt{big\_force} command that immediatly precedes or follows it and also cancels any \fmt{backup} command that follows it. \end{tabular} \end{center} \caption{List of format command primitives} \label{command-table} \end{figure} \section{Writing Prettyprinting Grammars} \begin{quote} ``Knowing \CWEB{} and its sources, it is clear to me that doing a good job (or even a fairly good job) about prettyprinting is not a simple task.'' Marc van Leeuwen \cite{vanLeeuwen96:pp:noweb} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent Yes, this is true. In terms of \pretzel{}, ``doing a good job about prettyprinting'' is writing a good prettyprinting grammar. For simple languages you might spend a day or two preparing a good grammar, but for more complex languages (and more complex wishes to the look of the output) you might spend weeks and still not be happy. \index{prettyprinting!grammars} \index{grammars!prettyprinting} \index{complex languages} \subsection{Modifying an existing grammar} If you're lucky, somebody else had done the work already for you. In such cases, simply grab a copy of the two \pretzel{} input files, run \t{pretzel-it} and off you go. The \pretzel{} homepage \cite{pretzel:homepage} should be a good starting point for the quest for a prettyprinting grammar for your language. \index{Pretzel!homepage} \index{homepage!Pretzel} But what if this grammar doesn't suit your preferences? What if it prettyprints ugly code? Well, then you have to plunge into the files and modify them. Making small changes that will work is quite easy. For example, if you only dislike the way certain symbols come out of the prettyprinter, look in the formatted token file and try to figure out, where you can change it. Or if you dislike forced line breaks at certain places, just go into the grammar and remove the \fmt{force} from the attribute definition. If your wishes cover more major aspects of the layout, then you should make a copy of the file and rename it to something that reflects the change. Also, you might put a new comment at the beginning of the file that describes who you are and what this new grammar does differently than the grammar you started from. Now you can start to experiment. The good thing about this is that you can always fall back to the original copy and start from there again. If you get your new grammar working, contact the \pretzel{} home page \cite{pretzel:homepage} so it can be added to the list of files for certain languages. Other people can then use your grammar and don't have to go through the same work again. For similar languages (like Java and \C{}) you could try to take a grammar for the first one and try to modify it that it fits the second one. In any case, studying existing grammars is always very helpful if you don't have much experience. \index{Java} \index{C} \subsection{Writing a new Grammar from Scratch} If you're unlucky, and you can't find a suitable grammar then you will have to start from scratch. If you're in this situation, there are two possible ways of continuing: % \index{writing grammars} \index{scratch} % \begin{enumerate} \item Most programming languages are context free and so there should be a context free grammar for your language available either in the reference works (i.e.~the books) that ``define'' the language, or somewhere in the internet, where there could be compilers for your language available in the source, and if so, a context free grammar for the parser of that compiler is almost always included there. You could start with such a grammar and simply add formatting instructions to the rules as you wish. \index{language definition grammars} \index{reference grammars} \index{compilers} \index{books} \item You could start entirely from scratch, look at the language and start writing a prettyprinting grammar that works with the code you are working on. This might seem more work than the first alternative, but sometimes is still feasible. \end{enumerate} To go with the first alternative, you will have to have a full blown language grammar available. But these grammars (as for example with \C{} or \CPP{}) tend to be rather large and ugly, resulting in prettyprinting grammars, that are difficult to understand and difficult to modify. However, a prettyprinting grammar doesn't have to be a full blown language grammar after all. The fact that such a grammar will solemnly be used to create a ``prettyprinted'' translation of a bit of source code it doesn't necesserily have to have any resemblence to a language grammar. In \PASCAL{} for instance, \res{for}-, \res{while}- and \res{else}less \res{if}-statements are normally formatted in a very similar way; so the grammar mustn't distinguish between the three constructs. This results in prettyprinting grammars that can be quite different from the normal grammars of the programming languages. In most cases they are much smaller. \index{prettyprinting grammars} However, if you start from scratch and don't want to use an existing reference grammar, you could still consult it once and again if you are stuck with your own one. Like the language grammar, the prettyprinting grammar must be able to parse {\em every} construct that will appear in the input. But it's no problem if the prettyprinting grammar might swallow code that isn't syntactically correct. We're talking Prettyprinters here and not Compilers. Sections \ref{sec:context:sensitive} and \ref{sec:debugging} will elaborate more on the issue of ``grammar correctness.'' In any case, having a look at available prettyprinting grammars in advance helps a lot. \index{pascal@\PASCAL} \subsection{Context Free versus Context Sensitive} \label{sec:context:sensitive} \index{context free grammars} \index{context sensitive grammars} Looking at the history of the prettyprinting method that \pretzel{} employs (see chapter \ref{chap:on:prettyprinting}), we can see that the grammars that the first systems started with were context sensitive. This means that there actually are ready to use context sensitive prettyprinting grammars around for many languages such as \PASCAL{} \cite{Knuth:web83} and \C{}/\CPP{} \cite{Knuth:CSS93}. There is even a system similar to \pretzel{} but with a more complete approach called {\sc SPIDER} \cite{Ramsey:CACM-32-9-1051} that amoung other things created a prettyprinter from a context sensitive prettyprinting grammar. \index{SPIDER} \index{WEB} So why does \pretzel{} use context free grammars anyway? The answer to this problem lies in the tools that \pretzel{} relies on. The prettyprinters that \pretzel{} generates are actually parsers, and instead of writing a whole new parser generator, \pretzel{} relies on the well known \UNIX{} tool Bison, that does just the work we need. But, in effect, Bison input is context free! Hmmm. \index{Bison} \index{parser generator} \index{UNIX} \index{Hmmm} Now context free grammars are a little more restrictive than context free ones, and so it is not possible to transform any context sensitive grammar of your choice into a context free one. This is unfortunate, but this is a fact we have to live with. My knowledge of formal language theory is not very deep, but I suspect that parsing with context sensitive grammars is not trivial and that this is the reason why no generators like Bison exist in a context sensitive flavour. \index{formal language theory} \index{parsing} \index{Bison} So context free is what we have to live with. From studying existing prettyprinting systems (again see chapter \ref{chap:on:prettyprinting} for details) it seems that context sensitive is the way to go in prettyprinting, and this seems bad for \pretzel{}.\footnote{I actually {\em is} a quite severe restriction and will probably be the reason why \pretzel{} will not be widely used in practice. The extension of being able to add \C{} code to the attribute definition only partially eases the situation (see section \ref{sec:adding:code} for details).} But \pretzel{} is a prototype and (at the moment) the best you can get as a prettyprinter generator and a context sensitive implementation of \pretzel{} is left for a following student generation to pursue. The good thing about context free grammars however is that every context free grammar is also a context sensitive grammar, and so --- if a context sensitive version of \pretzel{} is ever built --- every existing and working prettyprinting grammar can be used with the new system without a single change. At least this is good news. For more information on this topic, also see chapter \ref{chap:future:work} on ``Future Work.'' \index{restrictions of Pretzel} \index{good news} \subsection{Available Grammars} All those prettyprinting grammars that are available in \pretzel{} format are contained in the latest distributions of \pretzel{} (at least all that I know of). If you have a good grammar for your favourite programming language at hand, let me know and I'll include it in the distribution too. \index{available grammars} \index{prettyprinting grammars!available} All these input files are available individually from the \pretzel{} homepage \cite{pretzel:homepage}. So if your \pretzel{} installation is rather old, then surf to that URL and look if there's something new on the page. To date (July 9, 1997) I am aware of: % \begin{itemize} \item \C{} (by Felix G\"artner) \\ Directory: \t{languages/cee} \\ Files: \t{cee.ft} and \t{cee.fg} \index{Gaertner@G\"artner, Felix} \item \PASCAL{} (by Felix G\"artner) \\ Directory: \t{languages/pascal} \\ Files: \t{pascal.ft} and \t{pascal.fg} \item Java (for \noweb{} by Lee Wittenberg) \\ Directory: \t{contrib/leew} \\ Files: \t{java.ft} and \t{java.fg} \index{Wittenberg, Lee} \item Java (for \noweb{} by Felix G\"artner) \\ Directory: \t{contrib/noweb/java.latex} \\ Files: \t{javafx.ft} and \t{javafx.fg} \\ Comments: Based on the grammar by Lee Wittenberg with slight changes, but enhanced to do indexing. \item Java (for \noweb{} by Holger Uhr) \\ Directory: \t{contrib/huhr} \\ File: \t{javahu.fg} \\ Comments: Replaces \t{java.fg} from Lee Wittenbergs version in \t{contrib/leew}. \index{Uhr, Holger} \end{itemize} % Always see the \t{README} files in the directories for details. \index{gaertner@G\"{a}rtner, Felix} \index{Wittenberg, Lee} \index{Java} \index{Pascal} \index{C} \subsection{Debugging Prettyprinting Grammars} \label{sec:debugging} \index{debugging grammars} \begin{quote} ``Rather, it [the need to type `\verb"@;"' after each refinement] is caused by an error made in converting \WEB{} to \CWEB{} that was never corrected, namely a failure to recognise the fundamentally different roles of semicolons in \PASCAL{} and \C{}. In \PASCAL{} semicolons separate statements, whether simple (e.g., assignments) or compound, so if any such statement is followed sequentially by another one, a semicolon is required after the first; the requirement still holds if the first statement is a refinement. In other words, in Pascal one has `refinement $\rightarrow$ statement' always, without having to consider \verb"LINE_END", and without having to use `\verb"@;"' (either a real semicolon is required after it, or nothing is, e.g., when \t{ELSE} follows). In \C{} however, no symbol separates successive statements, but things like assignments are expressions rather that statements, and they only become statements by incorporating a following semicolon. Since refinements almost always stand for (compound) statements, they should be given that category; however in (Levy/Knuth) \CWEB{} they are given the same category as assignments, which is `expression'. This forces one to write a semicolon after each refinement, even though that really becomes a spurious empty statement; if such an empty statement would mess up the real syntax (the compiler would fail) then one has to write `\verb"@;"' instead.'' Marc van Leeuwen \cite{vanLeeuwen95:pp:layout:style} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent Almost certainly, the first experiences with your own (or other's) prettyprinting grammars will lead to situations where source code is not prettyprinted the way you wanted and you don't know why. The insight that follows from this situation is very frustrating: nothing comes for free! Searching for bugs in prettyprinting grammars is as necessary as in normal programs. \subsubsection*{The \t{error} Token} If a \pretzel{} prettyprinter can't handle a sequence of input code, it will output {\em nothing}, not even an error message. But there is still a way to notice this fact. There is a special \t{error} token that may be used in such circumstances. You can place it into your grammar at any place, and it will match a sequence of tokens not covered by the other rules in question. \index{error token} \index{robust grammars} A handy place to put an \t{error} token is right at the beginning of the grammar. Say, a \t{final} token is the token that everything reduces to in your grammar. To notice a parse error, you can for example write % \begin{verbatim} final : exp | stmt // check for parse errors: | error { "syntax error" } ; \end{verbatim} % and so the text ``syntax error'' appears in the output everywhere \pretzel{} wasn't able to parse the input. \index{syntax error} You may place the \t{error} token in any place you like, as long as it is on the right hand side of the colon. Using the \t{error} token in other places than at the end, you may produce grammars that are more robust and can handle unforseen constructs more flexibly. \subsubsection*{Watching the Parse} \index{watching the parse} \index{prettyprinting grammar!watching parse} The \t{pretzel-it} program offers a \t{-d} option that produces a prettyprinter which is in ``debugging mode'' by default. This means that during prettyprinting, the program will output a lot of debugging information to the standard error stream (usually the screen). This information displays what kind of token has been read from the input (and how it looks) and what rule of the prettyprinting grammar has been chosen. Additionally, the \t{-d} option produces a file that contains an analysis of your prettyprinting grammar. If your input name is, say, \t{foo}, then this file will be called \t{foo.output}. \index{pretzelit@\t{pretzel-it}!option \t{-d}} \index{d@\t{-d} option of \t{pretzel-it}} \index{debugging mode} Here's an example of the debugging output (taken from a run on the \t{small-example.simpas} example): % \begin{verbatim} Starting parse Entering state 0 Reading a token: Next token is 260 (IFif) Shifting token 260 (IF), Entering state 1 Reading a token: Next token is 266 (IDa) Shifting token 266 (ID), Entering state 4 Reducing via rule 7 (line 195), ID -> exp state stack now 0 1 Entering state 8 Reading a token: Next token is 259 (BINOP=) Shifting token 259 (BINOP), Entering state 11 Reading a token: Next token is 265 (NUM1) Shifting token 265 (NUM), Entering state 3 Reducing via rule 8 (line 196), NUM -> exp state stack now 0 1 8 11 Entering state 15 Reading a token: Next token is 261 (THENthen) Reducing via rule 9 (line 197), exp BINOP exp -> exp [...] Entering state 14 Reducing via rule 2 (line 102), stmt_list SEMI stmt -> stmt_list state stack now 0 Entering state 5 Now at end of input. Shifting token 0 ($), Entering state 19 Now at end of input. \end{verbatim} % Every time, the scanner reads a token, the token code (like \t{IF} or \t{ID}) is printed which is followed by the actual contents of the token (like ``\t{a}'' in case of the identifier). Every time the parser reduces a token, it prints the rule that it uses. The number of the rules and also the state information will become clear if you look at the \t{simpas.output} file and learn about the internals of the \pretzel{} parsing mechanism (by looking at the manual page \t{bison(1)}). \subsubsection*{Context Free again} As described above, context free grammars are pretty restrictive, sometimes even more restrictive than we like. Note that rules like % \begin{verbatim} decl_head id : int_like id ; \end{verbatim} % to turn an \t{int\_like} token into the head of a declaration if it is followed by an identifier are context senstive and therefore forbidden. \index{context sensitive grammars} \index{restrictions} See also the next chapter, especially section \ref{sec:tips:and:tricks} for a few more tips and tricks for writing and debugging prettyprinting grammars. \subsection{Experiences} \begin{quote} ``With \CWEB, there'll always be something someone wants and can't have, because it tries to do too much in its kernel. Witness the recent complaint in this newsgroup from someone trying to put makefiles in the \CWEB{} sources. \CWEAVE{} tries to be the perfect \C{} programming tool right out of the box, and so comes up completely unable to handle makefiles.'' Barry Schwartz \cite{schwartz94:use:of:prettyprinting} \end{quote} \index{Schwartz, Barry} \noindent Remember, writing good prettyprinting grammars is difficult. So don't overdo it. It's pretty difficult (if not impossible) to come out with a ``complete'' grammar that will handle all cases brilliantly. So if you're happy with the way your code looks, that's fine. If something turns out wrongly, ask yourself, what actually {\em is} wrong here? % ###################################################################### \chapter{\pretzel{} Hacking} \label{chap:pretzel:hacking} In this chapter we'll have a look into the guts of \pretzel{}. We'll see how the internals of \t{pretzel-it} work and what other nice things you can do with the system. This chapter is aimed at programmers who want to produce simple, efficient and elegant prettyprinters for their language. However, I recommend reading at least the first subsection about adding \C{} code to the rules, even when you dislike hacking. \section{Adding \C{} Code to the Rules} \label{sec:adding:code} \index{adding code} \index{C code in rules} Yes, you cann add your own \C{} code to the attribute definition parts of the formatted grammar and formatted token files. A typical application of this feature is to dynamically typeset constructed type names (as \res{typedef}s in \C{} or \res{class}es in Java) correctly. The problem with \pretzel{} is, that we would like to perform different actions depending on the context of the token that the prettyprinter finds. For example, in \C{} normal identifiers should be typeset in italics, but identifiers that are the names of \res{typedef}s should be typeset in bold. \pretzel{} can't handle this situation without tricky manipulations of the attribute definitions, because the type of grammar that \pretzel{} uses is essentially context free (see section \ref{sec:context:sensitive} for a discussion of related problems). \subsection{Example for Tokens} How handle this situation? \pretzel{} allows you to add \C{} code to your attribute definitions. Here is a small example, how this could be used in formatted token files: \begin{verbatim} [a-zA-Z][a-zA-Z0-9_]* ID { "{\\it " [escaped_underlines(yytext)] "}" } \end{verbatim} The purpose of this line is to scan tokens that are identifier names and return ``\t{ID}'' type tokens to the prettyprinting parser, but also to modify the appearance of the matched text before returning. In this example there is \C{} code inside the attribute definition. This code is encircled in angled brackets ``\t{[}'' and ``\t{]}'' and can be any sequence of \C{} statements with one central property: The code part must reduce to the \res{Attribute}$\ast$ class, i.e.~the return type must me a pointer to an \res{Attribute} object. The \res{Attribute} class is a special \CPP{} class that belongs to the \pretzel{} system and is contained in the runtime library.\footnote{A description of how to use objects of this class and related functions can be found in the \noweb{} file \t{attr.nw} in the directory \t{attr} of the \pretzel{} distribution.} \index{[, code delimiters} \index{code delimiters} \index{Attribute class} \index{attr@\t{attr.nw}} % attr.nw might also belong into this book? XXX To this effect, the {\it escaped\_underlines} function called above must have the syonpsis: % \begin{outp} \res{Attribute}$\ast$ \id{escaped\_underlines}(\res{char}$\ast$ \id{s}); \end{outp} % The matched text is accessible via a string (i.e.~a \res{char}$\ast$ variable) called \id{yytext}. The delimiters of code are angled brackets as explained above. If angled brackets appear in the \C{} code itself, any closing bracket must be escaped by a backslash in order for \pretzel{} to recognize it correctly. \index{escaped underlines} \index{yytext} To help simplify the synopsis of the \id{escaped\_underlines} function, we may use special functions in the runtime library that belong to the \res{Attribute} class. These are the two functions \id{create} and \id{join}. The \id{create} function takes a string (i.e~a \res{char}$\ast$) and turns it into an attribute. So, if you have written a function, say \id{esc\_ul}, that turns a string into the same string with escaped underlines, then an implementation of the function above could look like this: % \index{create} \index{join} % \begin{outp} \res{Attribute}$\ast$ \id{escaped\_underlines}(\res{char}$\ast$ \id{s}) \myforce\{\myindent\myforce\res{return} \id{create}(\id{esc\_ul}(\id{s})); \myoutdent\myforce\}\myforce \end{outp} % The \id{join} function simply joins two or more (up to ten) attributes together into an new one. \subsection{Example for Grammars} But you can do more with this feature. Here's an example code fragment that handles the ``correct'' formatting of \res{typedef}s in \C{}. In \C{} you can construct your own shorthands for types by using the \res{typedef} construct, thus making normal identifiers like \id{Length} to type names. Here's an example, if you're not aquainted with \C{}: % \begin{outp} \res{typedef} \res{int} \id{Length};\pretzelbigforce \id{Length} \id{l};\pretzelforce \end{outp} % The identifier \id{Length} has the status of a type name and this should be reflected in the typesetting style. So the way we want it would be like this: % \begin{outp} \res{typedef} \res{int} \res{Length};\pretzelbigforce \res{Length} \id{l};\pretzelforce \end{outp} The idea behind a simple solution to this problem is to use a simple lookup table to keep track of all identifiers that have been \res{typedef}ed. Then, if we have to prettyprint an identifier, we simply look into the table and from the result we know whether we can use boldface or italics. A prettyprinter for \C{}\footnote{Like the one in the {\tt languages/cee} subdirectory of the \pretzel{} distribution.} might have rules like these to handle \res{typedef} statements: % \begin{verbatim} typedef : TYPEDEF_LIKE INT_LIKE ID [ install($3); ] { $1 "\\ " $2 "\\ {\\bf " $3 "}" } ; \end{verbatim} % (We assume that \id{install} is a function that installs an identifier in the lookup table and that \id{lookup} is a function that tells us if an identifier is in the table.) \index{install} \index{lookup table} What we see here is called {\em starting code}. Starting code is code in angled brackets that is placed before the attribute definition. It can contain any sequence of \C{} code that you like and will be executed before the attribute of the reduced token is even touched. You can use it to place declarations of variables or any other actions that should take place before the attribute is pieced together. So here, in this rule, we install an identifier that is \res{typedef}ed into the table. The identifier is typeset in bold already (but you could put it into any font you like). Now, every time we handle an identifier within declarations or expressions, we lookup it's name in the table. A rule like this does the job: % \begin{verbatim} id : ID { [lookup($1) ? create("{\\bf ") : create("{\\it ")] $1 "}" } ; \end{verbatim} % Note that we are making use of the conditional expression of \C{}. Remember that the code within the attribute definition has to turn out as type \res{Attribute}$\ast$ and so we use the \id{create} function again to turn a string into an attribute. So here again we use code {\em within} attribute definitions and all in all, we can use identifiers as \t{id} tokens in the grammar and know that they are typeset correctly. \index{starting code} \index{ending code} Apart from code before the attribute definition and code within attribute definitions, there can also be code after the attribute definition which is called {\em ending code}. Ending code can be any kind of sequence of \C{} statements. They will be executed {\em after} the attribute definition has been put together and {\em before} the final token identifier id returned. So in effect you yourself may play God and return a token identifier yourself. The following extract from a formatted token file is an example: % \begin{verbatim} [a-zA-Z][a-zA-Z0-9]* ID { ** } [ return(ID); ] \end{verbatim} % Here, the \res{return} statement is executed just before the prettyprinting scanner itself returns the \t{ID} token, so here you could leave the ending code away and nothing would be changed. But of course, you could put an \res{if} statement there and return something else as you wish. The symbolic names of all the tokens may be accessed with the code parts simply by their names you gave them. Now you might wonder, what the sequence % \begin{verbatim} [a-zA-Z][a-zA-Z0-9]* ID [ return(ID); ] \end{verbatim} % would mean. Tricky you! Is this starting or ending code? Well, \pretzel{} doesn't want to care about these kind of questions, and so it simply declares them illegal. If you want to use either starting code, ending code or both, you {\em need} an attribute definition. \subsection{Summary} This is how \pretzel{} expects you to write code inside your \pretzel{} input files: % \index{code in attributes!summary} % \begin{itemize} \item Code fragments are bracketed within angled brackets. Any angled brackets that appear within the \C{} code must be escaped with a backslash. \item Starting code and ending code are written outside of the attribute definition. Both are totally optional, but if you want to specify either or, you need an attribute definition. \item Code parts within attribute definitions must return a pointer to an \res{Attribute} class object. \item Within the formatted token file, the matched text is visible to you in form of a \res{char}$\ast$ variable called \id{yytext}. The symbolic names of the tokens are available by the same name that \pretzel{} gives them. \item Starting code, code within attribute definitions and ending code is totally optional. But at any place where they are allowed, only one bracketed code bit may be placed. \end{itemize} % Common routines to escape identifiers, to build and manage lookup tables, to convert to and from \res{Attribute}$\ast$ or to output debug information can be found in the files belonging to the \C{} prettyprinter in the directory {\tt languages/cee} of the \pretzel{} distribution. \subsection{Tips and Tricks} \label{sec:tips:and:tricks} \index{tips and tricks} One thing I have found usefull is to slip debug output into the \pretzel{} input files via \C{} code added to the attribute definitions. For example, I have written a function called \id{debug\_print} that takes a string and an \res{Attribute}$\ast$ and outputs the contents of the attribute to \id{stderr}. Here is what it could look like: % \begin{outp} {\bf static} {\bf void} {\it debug\_print}({\bf char}$\ast$ {\it this\_is}, \pretzelopt9{}{\bf Attribute}$\ast$ {\it stuff})\pretzelforce{}\{ \pretzelindent{}\pretzelforce{}{\it cerr} $\ll$ \verb*|"*** "| $\ll$ {\it this\_is} $\ll$ \verb*|":"| $\ll$ {\it endl};\pretzelforce{} {\bf Latex\_cweb\_output} {\it os}({\it cerr});\pretzelforce{} {\it stuff}$\to${\it print}({\it os});\pretzeloutdent{}\pretzelforce{}\} \pretzelforce{} \end{outp} % \index{debug print} \index{Latex cweb output} % This will use a \res{Latex\_cweb\_output} object (see the file \t{output.nw} in the \t{output} directory of the \pretzel{} distribution or section \ref{sec:non:latex} for details) to output the contents of an attribute to the standard error stream. The idea now is to insert a code fragment that outputs the contents of an attribute at special places in the grammar, like for example before the prettyprinter returns: % \begin{verbatim} final : exp { "$" $1 "$" } [ debug_print("Final exp", $1); ] \end{verbatim} % This will output the contents of the expression \t{exp} to the standard error stream before reducing it to a \t{final} token and exiting. Also, \pretzel{} prettyprinters do not insert newlines into the output if they are not told to. So, if no special care is taken, most prettyprinters will output one single long line of prettyprinted code. This might upset some typesetting systems that have restricted input buffers and are used to handle one line at a time. This problem may be avoided by manually inserting newline characters from time to time into the output, as for example after every statement: % \begin{verbatim} stmt : exp semi { $1 $2 force "\n" } \end{verbatim} % This will lead to better readable input and will make a lot of formatting programs happier. \index{newlines} There are a couple of handy functions available that do stuff like escaping underlines and turning an attribute into a string. Look at the files \t{javafx.ft} and \t{javafx.fg} in the \t{contrib/noweb/java.latex} directory of the \pretzel{} distribution for details. They are self-contained \pretzel{} input files that have a hash table built into them and do all converting by themselves. \section{The \pretzel{} Interface} \label{sec:pretzel:interface} \index{Pretzel!interface} The actual \pretzel{} program (called \t{pretzel}) does only half the job of \t{pretzel-it}. It simply builds ready to use source code for the specified prettyprinter in terms of input files to the two standard \UNIX{} tools flex and Bison. Using these tools will result in compilable \CPP{} source code that contains the actual prettyprinting module. \pretzel{} prettyprinters consist of two parts: % \begin{enumerate} \item a {\em prettyprinting scanner} that cuts the input into small pieces (called {\em tokens}), and \item a {\em prettyprinting parser} that joins the tokens returned by the scanner together and does the actual prettyprinting. \end{enumerate} % Both, the scanner and the parser, are seperate modules with a well defined interface. In this section I will present this interface. \index{prettyprinting scanner} \index{prettyprinting parser} \subsection{The Prettyprinting Scanner} The prettyprinting scanner is a \CPP{} prettyprinting scanner class. Every prettyprinting scanner produced by \pretzel{} is a subclass of an abstract scanner class that looks like this: % \index{prettyprinting scanner class} % % why isn't this prettyprinted? XXX % \begin{verbatim} #include #include"attr.h" class Pscan { public: Pscan(istream*) {}; ~Pscan() {}; virtual int scan(Attribute**) = 0; }; \end{verbatim} % A \pretzel{} scanner must be associated with an \CPP{} input stream object that is passed to the constructor of the class. The scanner will read characters from this input stream when scanning. The actual scanning if performed inside the \id{scan} member function. It's return codes are integers and identify the token that it has just scanned. If the input is empty, it returns 0. \index{Pscan class} The subclass that \pretzel{} produces will always be a subclass of the above class. It's interface is similar: % % prettyprint this XXX % \begin{verbatim} class PSCAN_NAME : public Pscan { public: PSCAN_NAME(istream*); ~PSCAN_NAME(); int scan(Attribute**); }; \end{verbatim} % The name of the generated class is \t{PSCAN\_NAME} by default and has to be redefined using preprocessor macros, such as for example % \index{pscanname@\t{PSCAN\_NAME} macro} % \begin{verbatim} #define PSCAN_NAME Pscan_for_pascal \end{verbatim} % By default the name of the derived subclass will be \t{Ppscan}. A header file containing the derived scanner class could look like this (by default the header file is called {\tt Ppscan.h}). Note that there is no precaution against double inclusion. % \index{pscanh@\t{Pscan.h} header file} % \begin{verbatim} /* header file for a prettyprinting scanner */ /* NB: This file is NOT protected against double inclusion! */ #include "Pscan.h" // include abstract base class #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #endif class PSCAN_NAME : public Pscan { public: PSCAN_NAME(istream*); ~PSCAN_NAME(); int scan(Attribute**); }; \end{verbatim} % This is exactly the default header file that you can find in the \t{include} directory of the \pretzel{} distribution. If \pretzel{} is installed on your system, you should find this file (and the header file for the abstract base class) in the global \pretzel{} include directory too.\footnote{This directory will usually be called \t{/usr/local/lib/pretzel/include} or something alike.} \subsection{The Prettyprinting Parser} \index{prettyprinting parser interface} The interface to the prettyprinting parser is similar in structure to the prettyprinting scanner. We have an abstract base class called \t{Pparse} that has this interface: % \index{pparse@\t{Pparse} class} % \begin{verbatim} #include #include"attr.h" #include"output.h" class Pparse { public: Pparse() {}; ~Pparse() {}; virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*) = 0; }; \end{verbatim} % There are the usual functions to create and destroy a prettyprinting parser plus an overloaded virtual member function \id{prettyprint}. The normal use of \id{prettyprint} uses \CPP{} input and output streams. It reads from an input streams and writes prettyprinted code to the output stream. \index{prettyprint function} The second version of this member has an \id{Output} class pointer as second argument. This is a version for experts. See section \ref{sec:non:latex} for an example how to utilize this. The prettyprinting parser class which is actually generated is again a subclass of this abstract base class. It's name may be redefined using \C{} preprocessor macros. % \index{pparsename@\t{PPARSE\_NAME} macro} % \begin{verbatim} class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; \end{verbatim} % The two extra functions \id{debug\_on} and \id{debug\_off} enable and disable debugging output. Debugging output gives an indication what the scanner returns and what kind of rules the parser is reducing. It is really a lot of information.\footnote{The information provided using the \t{-d} option of \t{pretzel-it} program comes from using these functions (see section \ref{sec:debugging}).} \index{debug on function} \index{debug off function} \index{d@\t{-d} option of \t{pretzel-it}} As you can see, the name of the generated class is \t{PPARSE\_NAME} by default and has to be redefined using preprocessor macros, such as for example % \begin{verbatim} #define PPARSE_NAME Prettyprinter_for_pascal \end{verbatim} % By default the name of the derived subclass will be defined as \t{Ppparse} (note the three `p's). This is the default header file for the generated parser: % \begin{verbatim} /* header file for a prettyprinting parser */ /* NB: This file is NOT protected against double inclusion! */ #include "Pparse.h" // include abstract base class #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; \end{verbatim} % This file resides in the \t{include} directory of the \pretzel{} distribution and together with the header of the abstract base class is also is found in the \pretzel{} \t{include} directory of the system (if \pretzel{} is installed). \subsection{Example} A minimal file that utilizes a \pretzel{} prettyprinter could look like this: % \begin{verbatim} #include #include "Ppparse.h" int main () { Ppparse prettyprinter; prettyprinter.prettyprint(&cin,&cout); return(0); } \end{verbatim} % Firstly, the actual prettyprinter class is included. Then we declare a simple prettyprinter and simply call \id{prettyprint}. Here, the input and output streams are connected to the standard input and the standard output. If this \id{main} routine is compiled and linked with the objects produced from the output of \pretzel{}, the prettyprinter will work as specified in the two input files. The prettyprinting parser internally calls the prettyprinting scanner by its default interface. \section{Building a \pretzel{} prettyprinter by Hand} If you need to produce a prettyprinting module by hand you'll have to directly invoke \pretzel{}, flex, Bison and your \CPP{} compiler in the right order. To ease this, you can use the \t{Makefile} in the \PASCAL{} subdirectory of the distribution (\t{languages/pascal}). To produce (only) the prettyprinting parser from the file \t{pascal.fg} for example, you could type the following: % \begin{verbatim} $ pretzel -g pascal This is pretzel, version 2.0. Processing the formatted grammar file (pascal.fg -> pascal.y). No errors found. $ bison -d pascal.y pascal.y contains 21 shift/reduce conflicts. $ mv pascal.tab.h ptokdefs.h $ g++ -c -I$PRETZEL_INCLUDE -g pascal.lex.c \end{verbatim} % We assume that the \t{PRETZEL\_INCLUDE} environment variable points to the \pretzel{} include directory. The \t{-d} option of Bison will produce a token header file that the scanner expects (the scanner must know, which tokens the parser awaits and which token codes they have). The scanner expects these definitions under the name \t{ptokdefs.h}. \index{pretzelinclude@\t{PRETZEL\_INCLUDE} environment variable} \index{d@\t{-d} option of Bison} \index{token header file} \index{ptokdefs@\t{ptokdefs.h} header file} The above sequence of commands should leave a \t{pascal.tab.o} file in your directory. This is the object code of the prettyprinting parser with the default interface (i.e.~the generated class' name is \t{Ppparse} and is declared in the include file \t{Ppparse.h}). You can now use this prettyprinter in your own programs: by including the header file the prettyprinter class will become visible; by linking the object with your own program you'll get your executable. (Note that you'll need to provide a prettyprinting scanner youself in this case or simply produce a suitable one in a similar way using \pretzel{}.) \section{Obtaining a \pretzel{} Prettyprinting Module} In the preceding section I have explained how to produce a \pretzel{} prettyprinter by hand. Now we'll see how you can change the default interface of the produced prettyprinting scanner and parser. \index{prettyprinting module} \subsection{The Prettyprinting Scanner} Say, you need a prettyprinting scanner class called \id{Fooscan} in a header file called \t{Fooscan.h}. All you have to do is to make a copy of the default header file \t{Ppscan.h} (which you can find in the \pretzel{} include directory), change its name to \t{Fooscan.h}. Then you have to change the one single \res{\#define} statement therin, i.e.~instead of % \begin{verbatim} #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #endif \end{verbatim} % \index{pscanname@\t{PSCAN\_NAME} macro} % you'll have to write % \begin{verbatim} #define PSCAN_NAME Fooscan \end{verbatim} % Within your formatted token file, you'll have to tie in the same definition like this: % \begin{verbatim} %{ #define PSCAN_NAME Fooscan %} \end{verbatim} % It is important that this text appears in the declarations section of the formatted scanner file, i.e.~before the first line that contains the double percent sign `\verb"%%"'. Compiling and linking the source produced by \pretzel{} and flex you'll get the object code that contains the desired prettyprinting scanner. The scanner expects to find a token header file under the default name \t{ptokdefs.h} with definitions of the symbolic names and token codes of the tokens it should be able to scan. Either you produce this file by hand or you let Bison do the job for you (using the \t{-d} option if you have a prettyprinting grammar). Look into a standard \t{ptokdefs.h} file to see what it should contain. The name of the token header file \t{ptokdefs.h} may also be changed. You have to define the \t{PTOKDEFS\_NAME} macro within your formatted token file like this: % \begin{verbatim} %{ #define PTOKDEFS_NAME "fooscantoks.h" %} \end{verbatim} % Now the scanner will include the file \t{fooscantoks.h} and look for token code definitions in there. (Again, this redefinition must be in the declarations section of the formatted token file.) \subsection{The Prettyprinting Parser} Changing the interface of the prettyprinting parser works in a similar way as just explained for the prettyprinting scanner. The differences lie in the macro names that have to be redefined. The name of the derived prettyprinting parser class is \t{PPARSE\_NAME}. If you say in the definitions section of the formatted grammar file for example % \index{pparsename@\t{PPARSE\_NAME} macro} % \begin{verbatim} %{ #define PPARSE_NAME Foopp %} \end{verbatim} % then your prettyprinter class will be called \t{Foopp}. Internally it expects the prettyprinting scanner with it's default interface (i.e.~under the names \t{Ppscan} for the class and \t{ptokdefs.h} for the token header file). If you redefine the same macros as in the formatted token file, then you redefine the interface under which the prettyprinter expects the scanner. So lines like these in the formatted grammar would urge the prettyprinter to use a \t{Fooscan} class object for scanning: % \begin{verbatim} %{ #define PPARSE_NAME Foopp #define PSCAN_NAME Fooscan %} \end{verbatim} \section{Multiple \pretzel{} Modules in the same Program} \label{sec:multiple:modules} \index{muliple modules} Using multiple \pretzel{} modules within a single program has been greatly simplified by introducing the object oriented interface that has been explained in section \ref{sec:pretzel:interface}. The main thing is to change the names of the two scanners/parsers produced by \pretzel{} to something distinct and then to compile and link then together. That's the theory. But there's a problem here: the scanners and parsers produced by flex and Bison contain a couple of global variables whose names will clash when you try to link them together. This may be circumvented by using special options of flex and Bison to change the prefix of these globals when a scanner/parser is built. As I haven't needed this feature in the past (but only tested it), I haven't prepared an additional option to \t{pretzel-it} to do this in a nice and easy way. At the moment you'll still have to consult the manual pages \t{flex(1)}, \t{flexdoc(1)} and \t{bison(1)} for details. If this is a feature you need, tell me and I'll add it to \t{pretzel-it} (see also chapter \ref{chap:future:work}, ``Future Work''). \index{flex} \index{flexdoc} \index{Bison} Another thing that sounds interesting, but that I have not tested yet, is to use several instances of a single prettyprinter class produced by \pretzel{} in the same program. If you have ever tried it, I'm very interested in your results (see chapter \ref{chap:future:work}, ``Future Work'' again). \section{Prettyprinting for non-\LaTeX{}ians} \label{sec:non:latex} \begin{quote} ``Of course \CWEAVE{} does visual formatting, at least for the part that cannot be left to be visually formatted by \TeX: it issues forced line breaks, explicit changes of indentation level etc. The logical markup is really contained in the source document, and not (fully) in the intermediate file produced by \CWEAVE. However \CWEAVE{} does not do complete visual formatting: for instance many symbols like operators are produced as macros, so that you can easily change their appearance by overriding the default definitions, and breaking of long lines is also left to \TeX's line breaking algorithm.'' Marc van Leeuwen \cite{vanLeeuwen94:use:of:prettyprinting} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent \pretzel{} was build with \LaTeX{} in mind, but this doesn't necessarily mean that you are restricted to using this as back end of your prettyprinter. Through the way that \pretzel{} was designed, it is quite easy to extend it to work with any other markup formatting system. However, if you are opting for immediate screen output or things like \HTML{}, you're not lost either. First, we'll see how to handle the first case, and then let's go and look at things like \HTML{}. \index{HTML} \index{latex@\LaTeX} \subsection{Other Markup Formatters} Internally, all pieces of code that handle the direct output of characters or format commands to the output stream are encapsulated in a \CPP{} class called \res{Output}. The interface and implementation of this class are described in the \noweb{} source file \t{output.nw} in the \t{output} subdirectory of the \pretzel{} distribution. From looking at this file, you'll see that there is an abstract base class \res{Output} and that the standard class, which \pretzel{} prettyprinters use, is the \res{Latex\_cweb\_output} class\footnote{The name of this class results from the goal, to give a \LaTeX{} \CWEB{} touch to the output \cite{Schrod:CWEB:LaTeX}.}, a subclass of \res{Output}. It is within this subclass that the actual translation of the format command \fmt{force} into the string ``\verb+\pretzelforce{}+'' takes place for example. If you are going for something like Troff, you can similarly derive a new subclass of \res{Output} (for example by copying the original class) and simply replace the text bits like ``\verb+\pretzelindent+'' with the strings appropriate for Troff. Now, you have to instruct the generated prettyprinter not to use the default (\res{Latex\_cweb}-) output, but to use your new one. For this sake, the second version of the \id{prettyprint} member function of the generated prettyprinter may be used (see section \ref{sec:pretzel:interface}, ``The \pretzel{} Interface''). Simply pass an object of your new output class to the function and the prettyprinter will use it instead. By deriving a new subclass, Troff and \LaTeX{} prettyprinters may coexist peacefully. \subsection{Going for \HTML{}} What if you don't have a real markup formatting system at hand and want to go for something in the range of a vt100 terminal, line printer or \HTML{} page? Bad news is that you'll have to do without the full blown format command set. Proper interpretation of the line breaking commands \fmt{break\_space} and \fmt{opt}, the commands \fmt{backup} and \fmt{no\_indent} cannot be guaranteed in these cases. However, good news is that the \pretzel{} distribution contains a derived \res{Output} class called \res{Ascii\_output} that may be used to output prettyprinted code with this restricted command set to the screen (or to any device suitable for {\sc ASCII} characters). The format commands that cannot be executed properly are still valid, but result in no actions when outputting code. See the file \t{asciioutput.nw} in the \t{output} subdirectory of the \pretzel{} distribution for details.\footnote{An example \noweb{} prettyprinter that emits \HTML{} code can be found in the \t{contrib/noweb/cee.html} directory of the distribution. See also chapter \ref{chap:pretzel:meets:noweb}, ``\pretzel{} meets \noweb{}''.} \index{ASCII} % ###################################################################### \chapter{\pretzel{} meets \noweb{}} \label{chap:pretzel:meets:noweb} \begin{quote} ``\noweb{} is designed to meet the needs of literate programmers while remaining as simple as possible. [\ldots] The primary sacrifice relative to \WEB{} is that code is not prettyprinted.'' Norman Ramsey \cite{Ramsey:noweb:www} \end{quote} \index{Ramsey, Norman} \noindent The \noweb{} system \cite{Ramsey:j-IEEE-SOFTWARE-11-5-97} by Norman Ramsey is a simple tool for literate programming, a programming style first introduced and named by Donald Knuth in 1984~\cite{Knuth:CJ-27-2-97}. The main goal of this new style is to enhance the readability and understandability of a program's source code to an extent that makes it enjoyable to read. This section will explain, how the \pretzel{} system relates to this new ``paradigm'' \cite{Cordes:COMPUTER-24-6-52} and how it can be especially usefull in conjunction with \noweb{}. \index{Knuth, Donald E.} \index{literate programming} \index{noweb} This chapter explains how you can use \pretzel{} prettyprinters within \noweb{}. It expects that you know what literate programming is about and that you have had a go at using the \noweb{} system. The articles by Knuth \cite{Knuth:CJ-27-2-97}, Bentley \cite{Bentley:CACM-29-5-364} and Denning \cite{Denning:CACM-30-7-593} provide good and readable introductions to the field, while the paper by Cordes and Brown \cite{Cordes:COMPUTER-24-6-52} discusses the paradigm and the book by Knuth \cite{Knuth:LP92} provides a collection of related articles. Concerning \noweb{}, there is a lot of good introductory material available online (see for example the \noweb{} home page \cite{Ramsey:noweb:www}). As you will need \noweb{} anyway to install and run \pretzel{}, it is a good idea to try a small example now if you are unaquainted with it. Late sections will need detailed knowledge about the concepts of noweb as explained in the original paper by Ramsey \cite{Ramsey:j-IEEE-SOFTWARE-11-5-97} or the ultimate reference to \noweb{}'s interior by the same author \cite{Ramsey:noweb:hacking}. The \noweb{} extensions of \pretzel{} are still very much experimantal and far from making \noweb{} as powerfull as language dependent literate programming tools. \section{Prettyprinting in \noweb{} -- How it works} \begin{quote} ``They [the prettyprinting filters] can perform either or both of two tasks: \begin{itemize} \item choose fonts and glyphs to represent each source token \item choose indentation and line breaks of your code \end{itemize} I find these features of more cost than benefit (except possibly when preparing for book publication), but lots of people like them. Noweb takes the reasonable position that the programmer is the best judge of where to put the line breaks and how much to indent code. In some languages (Miranda, Haskell, awk, Icon), line breaks and/or indentation carry meaning, and to change them would be to change the meaning of the user's program.'' Norman Ramsey \cite{Ramsey96:noweb:filters} \end{quote} \index{Ramsey, Norman} % avoid UNIX terminology \noindent A primary design goal in developing \noweb{} was to have a literate programming tool that was simple enough to learn easily, and also suitable for easy modification and extensions. This second goal was achieved by it's ``pipelined architechture'' \cite{Ramsey:noweb:hacking}. Internally \noweb{} converts the input files into a stream of items which --- like in a pipeline --- are squeezed through special programs called {\em filters} that perform simple transformations on these data items. The format of the data items in the pipeline is called the ``noweb pipeline representation'' which interested readers can study in detail elsewhere \cite{Ramsey:noweb:hacking}. Devising a prettyprinter for \noweb{} means building a prettyprining filter for it. Such a filter can then be inserted into the pipeline. \index{noweb} \subsection{A \noweb{} Prettyprinter for \C{}} In the \t{contrib/noweb/cee.latex} you can find the definitions of a simple prettyprinter for \C{}. Change into this directory and look at the files \t{cee.ft} and \t{cee.fg}. They are normal \pretzel{} input files that have been modified slightly to work with \noweb{}. Before we look at these modifications, let's try to build a \noweb{} prettyprinting filter first. To do this, you can use the \t{-n} option of \t{pretzel-it} in the following way: % \begin{verbatim} pretzel-it -n cee prettycee \end{verbatim} % This will produce a \noweb{} prettyprinter called \t{prettycee} in the current directory.\footnote{The \noweb{} extensions of \pretzel{} must have been installed on your system in order for this to work. See the top \t{README} file of the \pretzel{} distribution for details.} This filter can then be sent into action using the \t{-filter} option of \t{noweave}. For an example, type: % \begin{verbatim} noweave -delay -filter prettycee ceetest.nw > ceetest.tex \end{verbatim} % This will mangle the \noweb{} input file \t{ceetest.nw} and output \LaTeX{} source to \t{ceetest.tex}. Now run it through \LaTeX{} and have a look at the result.\footnote{People who are interested in the internals of this operation should consult the file \t{pretty.nw} which contains the \noweb{} prettyprinter API and the file \t{nowebpretzelpp.nw} which contains a description of the interface between \pretzel{} and \noweb{}. Both can be found in the directory \t{contrib/noweb/general} of the \pretzel{} distribution.} What do you think? \index{n@\t{-n} option of \t{pretzel-it}} \index{noweb!prettyprinter API} \subsection{A \noweb{} Prettyprinter for Java} A pretty good \pretzel{} prettyprinter that works with Java and noweb can be found in the \t{contrib/noweb/java.latex/} directory of the \pretzel{} distribution. It features a fine tuned prettyprinting grammar that is quite robust (contributed in core by Lee Wittenberg), correct typesetting of class names (in bold, as god ment them to be) and rudimentary automatic indexing facilities. \index{Java} \index{Indexing with \t{noweb}} \index{Wittenberg, Lee} After installing \pretzel{} and making the file \t{prettyjava} (by simply typing `\t{make}'), try the filter on Java files of your own. The command to use then is: % \begin{verbatim} noweave -delay -filter prettyjava -index file.nw > file.tex \end{verbatim} % \index{delay@\t{-delay} switch} \index{filter@\t{-filter} switch} \index{index@\t{-index} switch} % Note that the \t{-filter} switch comes before \t{-index}. To get this stuff typeset correctly, your file needs to access the \t{pretzel-noweb.sty} \LaTeX\ style file (which gets installed when \pretzel{} gets installed). For this reason, you need to input it withing your document. The frames of my \noweb{} files always look like this: % \begin{verbatim} \documentclass{article} \usepackage{noweb} \usepackage{pretzel-noweb} % \begin{document} ... % rest of the noweb file \end{document} \end{verbatim} % Note that you still have to include the \t{noweb.sty} package before accessing \t{pretzel-noweb.sty}. \index{pretzelnoweb@\t{pretzel-noweb.sty}} \index{nowebsty@\t{noweb.sty}} This prettyprinter shows, how it can be made possible to include explicit format commands within the code a la \CWEB{}. For example you can say % \begin{verbatim} a:=1; //@cancel \end{verbatim} % and the \fmt{force}d line break that follows every statement will be canceled at this place. The only other format command that is possible here is \fmt{force}, which can be coded as \verb"//@/" (a little like \CWEB{}) or \verb"//@force", but in practice all other format commands can easily be added. Note that the format commands are comments in Java so they don't bother the tangling process. \index{cweb@\CWEB{}} \index{format commands!extra} \index{force@\fmt{force}} \index{cancel@\fmt{cancel}} \subsection{Writing Prettyprinting Grammars for \noweb{}} \begin{quote} "The most significant downsinde of not using \CWEB{} is lack of code prettyprinting; however, after prettyprinting code for quite some time I got tired of it and I am now a nuweb minimalist." Przemek Klosowski \cite{klosowski96:cweb:pp} \end{quote} \index{Klosowski, Przemek} \noindent Now, how do the \t{cee.ft} and \t{cee.fg} files differ from their non-\noweb{} counterparts? From your point of view, consider every code chunk as a seperate input to the prettyprinter you write. So the only things to note when building a prettyprinter for \noweb{} is that you may have arbitrary code fragments instead of full blown programs or functions, and that chunk uses may appear anywhere within the input code. Chunk uses come as individual lines into the prettyprinter. These lines are in raw pipeline representation, i.e.~look something like this: % \begin{verbatim} @use Foo Bar \end{verbatim} % The scanner must detect these lines and basicly must wrap them up into a token that doesn't get changed. Thus, the formatted token file contains a line like this: % \begin{verbatim} ^"@use\ ".* CHUNK { "\n" ** "\n" } \end{verbatim} % The `\verb"^"' ensures that the input matches from the beginning of the line. The two newlines in the attribute definition will result in the line being passed out of the prettyprinter unchanged. (The prettyprinter internally accumulates the code lines of an entire code chunk and then prettyprints it into a string. Then he cuts the prettyprinted code into lines before inserting it into the pipeline again. Lines that don't start with an `\verb"@"' are prefixed with ``\verb*"@text "''.) This chunk token now can be used within the formatted grammar. Because such a chunk token may appear everywhere in the text, it would be nice to have some rule that will stick a chunk token to any token that precedes it. As we have no possibility of using wildcards in token names, we use a simple trick: at the end of the grammar there is a rule like this for every possible token name: % \begin{verbatim} ^"@use\ ".* CHUNK { "\n" ** "\n" } ^"@".* IGNORE { "\n" ** "\n" } \end{verbatim} % The special \t{IGNORE} tokens result from another line in the formatted token file. This line reads as follows and is placed behind the line that matches chunk uses: % \begin{verbatim} ^"@".* IGNORE { "\n" ** "\n" } \end{verbatim} % As the prettyprinter input may contain other lines of internal \noweb{} representation code (they all start with `\verb"@"'), they need to be passed through the prettyprinter untouched too. This is what these two rules are good for. Note that the \t{ceetest.nw} file includes the \t{noweb.sty} \LaTeX{} style file as well as the file \t{pretzel-noweb.sty}. It is important that the \t{noweb} style comes before the \t{pretzel-noweb} style, because the latter redefines a macro from the prior (see also section \ref{sec:noweb:problems}). \subsection{Debugging} You may debug the prettyprinting filter by setting an environment variable called \t{PRETZEL\_NOWEB\_DEBUG} to the value ``\t{on}''. Debug information will be turned off again when you \t{unset} the variable. This is a simple, but easy to use method of controlling debug output. The output is much like the one explained in section \ref{sec:debugging} on page \pageref{sec:debugging}, and the tips and tricks from section \ref{sec:tips:and:tricks} come in handy too. Suggestions for improvements are welcome. I regularly run the parsing within Emacs (using the shell command possibility) ans then can easily search the debug output and follow how the tokens are put together. \subsection{Making the Best Use of It} \begin{quote} ``The one area where language dependent LP tools are ahead is identifier indexing, but I suspect that for \CPP{}, this is an almost impossible task anyway.'' Matthias Neeracher \cite{neeracher96:lp:indexing} \end{quote} \index{Neeracher, Matthias} \noindent Having understood how \noweb{} prettyprinters differ from normal \pretzel{} prettyprinters, it is easy to convert files in either direction. But now, we also get language dependent information within the prettyprinter nearly for free and we can for example start to build an index of identifier definitions and uses. For example, in the formatted token file, you could write: % \begin{verbatim} [a-zA-Z][a-zA-Z0-9_]* ID {"%\n@index use " + ** + "\n" "{\\it " [escaped_underlines(yytext)] "}" } \end{verbatim} % Here, every identifier will finally be preceded by a line that will tell the indexer of \noweb{} about the appearance of the identifier in this chunk. See the ``\noweb{} Hacker's Guide'' \cite{Ramsey:noweb:hacking} for details on the keywords that are allowed. But note, that if you're doing it this way the \t{-index} option of \t{noweave} has to appear {\em after} the \t{-filter} option on the command line. \subsection{Some Naming Conventions} \index{naming conventions} If you are looking at example files of \noweb{} prettyprinting filters, it's quite handy to notice some conventions that I have followed. The formatted grammar and the formatted token file should carry a name as a clear indication what programming language they contain (e.g. \t{cee.ft} or \t{java.fg}). The prettyprinting filter for \noweb{} that is produced should be called \t{pretty...} with the dots replaced by the programming language name (e.g.~\t{prettycee} or \t{prettyjava}). In the development directories you'll find special \noweb{} files meant to test the prettyprinters, not to be of any programming use. They include most of the syntax constructs of the programming language in question. These files are very instructive when building a new prettyprinter for noweb or testing one that you have changed. \section{Problems} \label{sec:noweb:problems} \index{noweb!problems} \begin{quote} ``I think the problem here is not so much that prettyprinting is inherently bad as that many languages don't benefit from it so much. \ALGOL{} and \PASCAL{}, I believe, benefit quite a bit from appropriate prettyprinting. These are languages where you write out a lot of whole words: `begin', `end', `do', `then' \ldots\ You get the idea. Languages like \C{} and Icon depend a lot on symbolic notation. For the large part, all \CWEB{} does is replace one set of symbols with another that some people happen to prefer. But, still, \CWEB{} puts reserved words and defining words in boldface and identifiers in italics; what of that? In \PASCAL{}, doing that helps mark out the form of a construct. In \C{}, on the other hand, the constructs are delimited by things like parentheses and braces, and so putting things in different typefaces doesn't help that much. OK, \CWEB{} indentifies, but you don't need weave to do that; Emacs can do that for you, or you can do it yourself, and the web source will benefit from it. The main thing that I might want from \noweb{} but don't get is typesetting of comments, and I can live without that because I don't need a great many comments.'' Barry Schwartz \cite{schwartz94:use:of:prettyprinting} \end{quote} \index{Schwartz, Barry} \noindent Handling of comments in prettyprinting remains an unsolved problem to date (see section \ref{sec:open:pp:problems}). This is partially due to the fact that that comments can crop up anywhere in the code and that they themself can again contain quoted code. With \noweb{} this problem isn't so severe, because chunks mostly do not contain a lot of comments as they are moved to the documentation parts of the literate program. But still a nice way of handling comments needs to be found. Also, quoted code in documentation chunks isn't prettyprinted. This is partially a deficit of the prettyprinter API and partially a structural problem. One would need two distinct prettyprinters to handle normal chunk code and quoted code seperately because you don't want to have forced line breaks within documentation. Another problem arises from the \t{noweb.sty} \LaTeX{} style. The environment for setting code naturally is rather restrictive and a macro needs to be changed in order to allow the \pretzel{} macros to work correctly.\footnote{I'm not a \TeX{} freak after all. Thanks to Lee Wittenberg for his help on this.} All this signals, that \pretzel{} an \noweb{} have not become real friends yet; they still have to work on their relationship. \index{noweb.sty} % ###################################################################### \chapter{On Prettyprinting} \label{chap:on:prettyprinting} \begin{quote} ``\noweb{} does automatic indexing and cross-referencing for some languages, including \C{}, Icon, \TeX, and Standard ML. Some people have made it prettyprint other language, like Icon and Object-Oriented Turing. I haven't been overwhelmed by the results, but then I'm notoriously difficult to convince of the value of prettyprinting.'' Norman Ramsey \cite{ramsey94:use:of:prettyprinting} \end{quote} \index{Ramsey, Norman} \noindent The term {\em prettyprinting} means the rearrangement of a program's source code to illuminate it's logical structure and thus enhance readability. The term goes back to Henry Ledgard and his ``Programming Proverbs''~\cite{Ledgard75}. Prettyprinting has become a field of interest because many of todays popular programming languages are so called ``free-format'' languages, where there are basically no column-position or line-boundary restrictions on statements, declarations, or comments. \index{Prettyprinting}\index{free format@``free format'' languages} \index{Ledgard, Henry F.} As a matter of fact, formatting and all other aspects of readability depend heavily on personal taste and skill. This has lead to a wide range of suggestions and standards concerning the formatting of programming languages, especially for the \PASCAL~\cite{Jensen85} language~\cite{Arab92,Bailes84,Bates81,Bond79,Crider78,Grogono79,Gustafson79,Heckert85,Ledgard77,Marca81,Peterson77,Mohilner78}.\label{formattingstandards} The consistency of these proposals has also enabled construction of automatic formatting algorithms and tools that are usually called {\em prettyprinters\/} (or {\em indenting programs\/}). In the literature general examples of prettyprinters have been presented among others for the languages \ALGOL~\cite{McKeeman65,Scowen71}, PL/I \cite{Conrow70}, \LISP~\cite{Goldstein73,Hearn79,Waters83,Waters92}, Ada \cite{Norris84}, and of course for \PASCAL~\cite{Hueras77,Jackel80,Bates81,Winter89,Arab92}. \index{Personal taste}\index{Taste!personal}\index{pascal@\PASCAL} \index{Formatting standards}\index{Formatting algorithms} \index{Prettyprinters!for other languages} \index{Indenting programs|see{Prettyprinters}} \index{algol@\ALGOL}\index{PL/I}\index{lisp@\LISP}\index{Ada} \index{pascal@\PASCAL} However, technological advance in the area of automatic typesetting has led to a set of powerful formatting tools called {\em typesetters}, or {\em typesetting systems}, of which \TeX~\cite{TeXbook} is maybe the most apparent to computer scientists. These tools allow the preparation of documents in high quality suited for publication. Among the features of these systems are automatic line- and page-breaking, powerful macro-processing facilities and convenient devices for typesetting mathematical formulas. Seen in this light, automatic program formatting is only a simple instance of automatic typesetting \cite[p.~652]{Rose81}. So prettyprinting algorithms that rely on professional typesetters can be simpler and produce better results at the same time, because a lot of the formatting problems (e.g.~alignment, line-breaking, typesetting mathematical formulas) can be taken on by the typesetter. \index{Automatic typesetting}\index{Typesetters}\index{Typesetting systems}\index{tex@\TeX}\index{Program formatting} In this chapter deals with the general issue of prettyprinting. It places a wider view on the field and tries to locate the \pretzel{} system within the latest research. \section{Prettyprinting with Format Commands} \label{fmt-commands} \begin{quote} ``Well, I must confess, I was very close to throwing the whole \CWEB{} away and switching to something without any prettyprinting, like {\tt nuweb} or \noweb{}. I installed {\tt nuweb}, rewrote the {\tt Matrix2D} example into it, ran it through and -- returned back to \CWEB{}. I probably got spoiled by the nice-looking output it produces -- almost always.'' Jan Dvorak \cite{dvorak95:cweb:nice:output} \end{quote} \index{Dvorak, Jan} \noindent The prettyprinting method used by \pretzel{} can be called {\em prettyprinting with format command primitives} and goes back to a similar method used by Knuth in his original \WEAVE\ system for \PASCAL\ (see section \ref{relatedwork} for details). Like most other prettyprinting algorithms this method functions similar to a {\em compiler}, i.e.~an input file is processed and translated into an output file according to special rules. Here, the input file is the patch of source code that shall be prettyprinted and the output file is the text suited for the typesetter. The translation rules represent the special way in which source code should be formatted. \index{pascal@\PASCAL}\index{weave@\WEAVE}\index{Knuth, Donald E.} \index{Compilers!and prettyprinters} The main assumption is that we have a text formatter that uses {\em control sequences\/} (or {\em tags\/}) inside the actual text body for specifying all the different ways of formatting (such as fonts, indentation, spacing, etc.). Another term for this way of formatting control is {\em in-text procedural markup\/} and systems using this technique are commonly called {\em document compilers} (though this might only refer to the way they work, not to viewing text processing as programming). Common examples of such typesetting systems are \TeX\ and the \UNIX\ tools Nroff/Troff. % \index{Control sequences}\index{Tags}\index{In-text procedural markup} \index{Markup}\index{Procedural markup}\index{Document compilers} \index{Compilers!for documents}\index{tex@\TeX}\index{unix@\UNIX} \index{Nroff}\index{Troff} % During the processing of the input the only thing it does is to enrich the stream of incoming information with special control sequences that I call {\em format commands} (or {\em format command primitives}). These commands are tags that are left for the typesetter to interpret. The set of format commands used by \pretzel{} is basically the initial set used by Knuth. % \index{Knuth, Donald E.!command set by} % To understand this procedure, see chapter \ref{chap:using:pretzel}. The original documents by Knuth \cite{Knuth:web83} and Knuth and Levy \cite{Knuth:CSS93} present the algorithm in (in)formal detail. \section{A Short History of Prettyprinting} \label{relatedwork} \begin{quote} ``Nevertheless I strongly disagree with people saying that pretty-printing is not worth the effort for anyone in general; this depends very much on ones particular situation and purpose. In some cases pretty-printing may even be the main reason to opt for literate programming.'' Marc van Leeuwen \cite{vanLeeuwen95} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent In this section I will give a brief chronological overview over the area of prettyprinting, try to structure the field, and will show, how the present system fits into it. \index{History of prettyprinting}\index{Prettyprinting!history} \subsection{Historical Notes} The prettyprinting of code has a long tradition that not only originates from the compulsion to typeset programs for publication. The readability or even the sheer beauty of a prettyprinted algorithm have also been a key motivation to this part of computer science. \index{Tradition}\index{Beauty} The first people to call special attention to formatting issues were probably Peter Naur, Myrtle Kellington and William McKeeman. While Myrtle Kellington, as executive editor of ACM publications, helped to develop high quality programming-language typography standards, Naur was the first to include such formatting standards into his report on the \ALGOL~60 language \cite{ALGOL-Report} and McKeeman was the first to present a prettyprinting algorithm for it \cite{McKeeman65}. This reaches back to the early 60s. In fact, McKeeman`s algorithm is the first actual prettyprinter to be found in the literature. Its purpose was % \index{Naur, Peter}\index{Kellington, Myrtle}\index{McKeeman, William} \index{ACM}\index{algol@\ALGOL}\index{Prettyprinter!first} % \begin{quote} ``[\dots] to edit \ALGOL~60 text that is difficult to read because, for example, the \ALGOL\ has been transcribed from printed documents, or written by inexperienced programmers [\dots]'' \end{quote} % Later, other prettyprinters were presented for PL/I~\cite{Conrow70}, \LISP~\cite{Goldstein73}, and finally \PASCAL~\cite{Hueras77}. These systems simply looked at the input text searching for special keywords. When encountering a keyword (which could be a \res{begin} or an opening brace, for example) a certain action would be triggered which would result in a line break, change of indentation, etc. \index{PL/I}\index{lisp@\LISP}\index{pascal@\PASCAL} \index{Prettyprinters!running on keywords} In these first approaches to the issue of prettyprinting the basic actions that prettyprinting includes were already visible. These concern (in order of importance):\footnote{In the late 70s there was one additional point on this list, namely the introduction of `connector lines' into the prettyprinted output \cite{Clifton78,Ramsdell79}. But this method hasn't found too much support since.} \index{Connector lines}\index{Prettyprinters!basic actions} \index{Basic actions of prettyprinters} \label{basic-actions} \begin{itemize} \item indentation and folding (i.e.~determining line breaks) of source code \item the additional spacing of syntactic constructs (like expressions) \item using additional typographic means (e.g.~different fonts) \end{itemize} \index{Indentation}\index{Folding}\index{Spacing!additional} \index{Additional spacing} The main disadvantage of the early systems was their language dependence. The style of prettyprinting was hard-wired into the system, which was basicly a big ``case'' switch over all known constructs that were to be treated specially. The main advantage of them, however, was their simplicity and their error handling capabilities (which is also the reason why such and similar tools are still widely used today). But it was soon clear that this approach wasn't adequate and that structural changes had to be made to the concept. \index{case@``case'' construct}\index{Early prettyprinters} \index{Prettyprinters!early systems} In their paper titled ``A One-pass Prettyprinter'' \cite{Hearn79} Hearn and Norman introduce a fundamentally new idea into this area. They simplify the whole concept of prettyprinting by introducing structure. \index{Hearn, A. C.}\index{Norman, A. C.} \begin{quote} ``The new method that we propose here will be described in terms of a pair of coroutines. One of these will be responsible for producing a stream of characters that represent the program being printed, the other makes decisions about how these characters should be displayed.'' \cite[p.~52]{Hearn79} \end{quote} This is a fundamental distinction, namely that between {\em formatting policy\/} and {\em formatting algorithm\/} \cite{Bailes84} and is a vital step on the road to language independence.\footnote{This idea however has also introduced a slight blur in the terminology, as some authors refer to prettyprinting as consisting only of the actual ``printing'' on paper (i.e.~the formatting algorithm) \cite{Oppen80,Jokinen89} and others still mean the entire process.} \index{Formatting policy}\index{Formatting algorithm} \index{Algorithm-policy distinction}\index{Policy-algorithm distinction} \index{Coroutines} A problem that arises from this separation is: how do the two coroutines communicate? Hearn and Norman use a simple FIFO buffer in which the first coroutine inserts text and ``special markers'' that indicate its decisions on the policy. These markers were mainly special blanks that indicate possible line breaks. \index{FIFO buffer}\index{special markers@``special markers''} \begin{quote} ``The markers will contain enough information for the formatting process to discover what level of indentation would be appropriate to use were a line break to be inserted at that point.'' \end{quote} This resembles a special kind of `communication protocol' and is the first hint to a thing that I have called `format command primitive' throughout this chapter. Other authors \cite{Jackel80,Oppen80,Waters83,Blaschek89,Rubin83,Rose81,Jokinen89} have taken up this idea and have introduced different sets of format commands that change and increase the communication facilities between these two processes. The two most elaborate to date are those of Rubin \cite{Rubin83} and that of Knuth and Levy \cite{Knuth:CSS93}, that is used here. \index{Communication protocol}\index{Format commands} \index{Rubin, Lisa F.}\index{Knuth, Donald E.}\index{Levy, Silvio} The separation introduced by Hearn and Norman is an example of `separation of concerns': the language dependent parts of prettyprinting are separated from the actual typesetting issues that arise, when putting text to paper. Blaschek and Sametinger \cite{Blaschek89} call this a distinction between ``language dependent front end and language independent back end''. \index{Hearn, A. C.}\index{Norman, A. C.}\index{Separation of concerns} \index{Language (in)dependence}\index{Prettyprinting!language (in)dependence} \index{Blaschek, G.}\index{Sametinger, J.} \index{Front end}\index{Back end}\index{Language dependent front end} \index{Language independent back end} \subsection{The Language Dependent Front End} The earliest suggestions how to build the language dependent front end go back to Oppens fundamental paper on prettyprinting \cite{Oppen80}. Though his main concern is the language independent back end, he makes suggestions about the ``preprocessor'' that should drive it. The main idea is to make a full syntactic parse of the prettyprinted code and to use the resulting parse tree to drive the prettyprinter. The format commands are either assumed to be implicit in the tree (i.e.~every single branch is treated as a structural block) or they are explicitly inserted into the tree during the parse. Oppen writes: % \index{Oppen, Derek C.}\index{preprocessor@``preprocessor'' for prettyprinting} \index{Parse tree}\index{Implicit format commands}\index{Explicit format commands}\index{Format commands!explicit}\index{Format commands!implicit} % \begin{quote} ``First, notice that the information needed by the prettyprinter can often conveniently be represented directly in the grammar [\dots]. We modify the grammar of the language to contain prettyprinting information as above, where [\dots] [the formatting commands] are nonterminals mapping only the empty string.'' \cite[p.~475]{Oppen80} \end{quote} This aspect has at last enabled people to use formal methods to describe layout rules. Mateti's paper \cite{Mateti83a} is another approach in the same direction and is the first to adapt this method to \PASCAL.\footnote{ It is interesting that Mateti's solution was the result of formalization (due to verification needs) and that Oppen's proposals emerged from the language independent nature of his approach.} The fact that rules for layout and grammar are often closely related \cite{Leinbaught80} also is a strong indication that this method is in fact adequate. The trend towards formal specification in this area has indeed been ``very fortunate'' \cite{Woodman86} and has also proved to be useful in other areas, such as syntax-directed editors \cite{Rubin83}. \index{Formal methods}\index{Mateti, P.}\index{pascal@\PASCAL} \index{Oppen, Derek C.} \index{Syntax-directed editors}\index{Editors!syntax directed} To this end Rose and Welsh \cite{Rose81} have advocated the integration of format rules within the language syntax on the language design level. They state that ``program format decisions [should be put] in the domain of the language's designer, rather than its several implementators or numerous users, which implies uniformly formatted programs of improved readability and therefore usability.'' \cite[p.~651]{Rose81} Their idea does {\em not} try to impose rigid formatting rules on users of existing or future languages. Instead they propose a metasyntax and a set of guidelines that constrain and direct the language designer in the placing of format commands. These format commands include commands for indentation, as well as for line breaks and optional line breaks (so called ``fold options''). The metasyntax and the guidelines only effect rather global issues of formatting but ensure consistency across language borders. They also present a folding algorithm that implements the format commands from their list. \index{Rose, G. A.}\index{Welsh, J.}\index{Rigid formatting rules} \index{Metasyntax (Rose and Welsh)}\index{Guidelines (Rose and Welsh)} \index{Folding algorithm (Rose and Welsh)} This last approach by Rose and Welsh is currently the `state of the art' in program layout issues. Woodman has published a thorough discussion of this scheme and has proposed refinements \cite{Woodman86} that however do not alter the main points. It is an approach that in some way surpasses the area of prettyprinting in that it forces the formatting grammar to be equal to the language reference grammar. However, Knuth shows that a prettprinting grammar can be much simpler than a full-size language grammar, because it is able to treat semantically different contructs equally as they are formatted in the same way (e.g.~\res{if}, \res{for} and \res{while} statements). \index{State of the art}\index{Woodman, M.}\index{Knuth, Donald E.} \subsection{The Language Independent Back End} The language independent back end implements the formatting algorithm. It actually makes the formatting decisions that the formatting policy has outlined and communicated to it via the format commands. The main concern of most algorithms is line breaking (or {\em folding\/}). The proposals by Rose and Welsh \cite{Rose81} and Oppen \cite{Oppen80} have been the most influential ones on other systems \cite{Waters83,Jokinen89,Blaschek89} in the literature. However, in both articles the authors refer to the future of their proposals for the formatting algorithm: % \index{Formatting policy}\index{Folding}\index{Language independent back end} \index{Rose, G. A.}\index{Welsh, J.}\index{tex@\TeX} % \begin{quote} ``The changes advocated must be seen in the light of current technological advances. Automatic program formatting is a very simple instance of automatic typesetting, as that provided by Knuth's TEX system for technical or mathematical text.'' \cite[p.~652]{Rose81} ``It [the algorithm] is not, however, as sophisticated as it might be, and certainly cannot compete with typesetting systems (such as TEX) for preparing text for publication.'' \cite[p.~466]{Oppen80} \end{quote} As the \WEB\ system shows, \TeX\ has been used as a back end for a prettyprinter, but it has remained the only one that I am aware of. This leads to the question, why so little prettyprinters faciliate typesetters as back ends for their output? This question is very striking, as typesetters offer powerful capabilities, and for example, \TeX's line breaking algorithm has been advocated to be very suitable for exactly this task \cite{Knuth-Plass81}. \index{web@\WEB}\index{tex@\TeX} Oppen gives an answer to this in his paper: % \begin{quote} ``However, it [the algorithm] seems to strike a reasonable balance between sophistication and simplicity, and to be appropriate as a subcomponent of editors and the like.'' \cite[p.~466]{Oppen80} \end{quote} \noindent It is surely the question whether you are prettyprinting on screen or preparing a publication. But the other part of the answer is maybe not so obvious and has to do with the traditional fears in the programming community. A lot of prettyprinters have been built as parts of larger programming environments and were constituent parts of this larger system. A lack of modularity in the design (as for example the fundamental distinction presented in these sections and visialized in figure \ref{pp-concept}) often makes the resuing of subcomponents impossible. The prettyprinters hide somewhere in the larger system and are difficult to extract. \index{Reuseability}\index{Modularity} Another point is that an old habit of programmers is their strive for independence. They do not want their systems to rely on other systems. But this habit is hopefully getting less frequent today. \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/pp-concept.latex} \end{center} \caption{The module structure of modern prettyprinters} \label{pp-concept} \end{figure} \subsection{The Set of Format Commands} The format commands passed between the front end and the back end of the prettyprinter are the only means to convey the formatting policy to the actual formatter (see figure \ref{pp-concept} that visualizes the modularity of a prettyprinter). This means that every typesetting feature must be expressible in them. In conjunction with this work it is important to ask, if the command set provided in the current \pretzel\ system is sufficient to format every desired feature that we can possibly think of. The answer is clearly `No!', as there still are open prettyprinting problems. We will have a look at them later. But just how sufficient is the command set? \index{no@``No''}\index{Sufficiency of command set} \index{Command set!sufficiency} First we'll look at whether it allows full control over line breaks and indentation. A detailed comparison shows that the command set used by Rose and Welsh is a subset of Knuth's command set (\fmt{indent}, \fmt{outdent}, \fmt{force}, \fmt{breakspace}, \fmt{opt}).\footnote{ The commands used by Rose and Welsh are denoted by the special symbols {\em m, o, r, i} and {\em s}. A stack is used to keep track of the indentation of the preceding lines. The symbol $m$ pushes the current horizontal print position onto the stack and the symbol $o$ pops the stack again. The metasyntax insists that every string produced from a non-terminal is bracketed by an $m$\dots$o$ pair. As no $m$ and $o$ are allowed elsewhere in a rule body, the amount of indentation is always restored to the prevoius value during formatting. The symbol $r$ denotes a line feed and a carriage return to the margin that is stored in top of the stack, whereas $i$ increments the top-of-stack margin value and then performes an $r$. The $s$ symbol is used to emphasize strings produced from a rule of the grammar. It is only allowed at the beginning of a rule body and directs the folding algorithm to force line breaks before and after the string produced from this rule. Optional line breaks (so called {\em folding options\/}, denoted `[$i$]' or `[$r$]') can be inserted between the non-terminals in the rule body. The most obvious analogy is the $i$ symbol. It corresponds to the sequence \fmt{indent}, \fmt{force} and since every indent is followed by a \fmt{force} or made superfluous by a matching \fmt{outdent} you may transform every occurence of \fmt{indent} into an optional $i$. The $r$ symbol, performed inside the $i$, denotes a \fmt{force} command. By popping the margin stack, the $o$ symbol plays the role of the \fmt{outdent} command. The two fold options `[$r$]' and `[$i$]' correspond to \fmt{break\_space} and \fmt{opt}.} Rose and Welsh in fact show by example, that any language syntax can be transformed into a formatted syntax that in itself is capable of specifying all desirable folds and changes of indentation. The main precondition for this transformation is, that the starting grammar is context free. None of the five basic commands is superfluous (as we have seen in the first part of this chapter) so we can call these basic commands the {\em necessary command set\/}. \index{Knuth, Donald E.}\index{Welsh, J.}\index{Rose, G. A.} \index{Context free grammar}\index{Necessary command set} The necessary command set enables the first point of the basic actions of a prettyprinter mentioned on page \pageref{basic-actions}. The other two points (additional local spacing of syntactic constructs; using different fonts) are things that depend on the capabilities of the typesetter and are not so much a question of the format command set. Thanks to procedural markup, as long as the prettyprinter allows us to insert strings between any two tokens at lexical level we are able to handle these two points too. However, in Rubin's rather assembler like command set \cite[p.~122]{Rubin83} we see that the necessary command set still lacks full control over vertical and horizontal spacing. One can argue over what parts of this issue belong into the domain of the typesetter and what should be left to the user's control, but there surely is an obvious need to express additional vertical separation in terms of a simple format command. In our case this is the \fmt{big\_force} command. \index{Procedural markup}\index{Markup}\index{Lexical level} \index{Rubin, Lisa F.}\index{Assembler like command set} \index{Command set!assembler like}\index{Spacing!vertical} \index{Spacing!horzontal} \index{Format commands!big force@\fmt{big\_force}} \index{big force@\fmt{big\_force}} The other command that gives better control over horizontal space is \fmt{backup}. Both \fmt{backup} and \fmt{big\_force} can be simulated by sequences of commands from the necessary command set.\footnote{The sequence `\fmt{force}, \fmt{backup}' is equal to `\fmt{outdent}, \fmt{force}, \fmt{indent}' and `\fmt{big\_force}' is something like `\fmt{force}, \fmt{null}, \fmt{force}', depending on the exact interpretation of the typesetter.} So they are not necessary but convenient short-hands. We will call them, together with the basic commands the {\em convenient command set\/}. \index{Format commands!backup@\fmt{backup}}\index{backup@\fmt{backup}} \index{Convenient command set}\index{Command set!convenient} Typesetting lines of code flushleft is not a feature commonly needed in modern structured programming languages, except in \C/\CPP\ when using preprocessor directives (and still they do not belong to the actual language itself). The \fmt{no\_indent} command caters for them but it is hardly necessary in other languages, where alone the idea of excluding single lines from the overall indentation frame violates all rules of good program layout. \index{c@\C}\index{c++@\CPP}\index{Format commands!no indent@\fmt{no\_indent}} \index{no indent@\fmt{no\_indent}} Finally the \fmt{cancel} command does not add any striking new features to the command set. It just allows more flexibility in the placement of format commands in the output. A well placed \fmt{cancel} command can obliterate a dozen rules of your prettyprinting grammar and thus can deflate prettyprinting grammars very much. So if you define sufficiency as incorporating convenience and flexibility we could call this whole set of presented commands a {\em sufficient command set}. This, however, naturally excludes the open problems mentioned in the next subsection. The two subsets of this sufficient command set are summarized in table \ref{command-set}. \index{Prettyprinting grammar!deflating}\index{Deflating prettyprinting grammars}\index{Format commands!cancel@\fmt{cancel}}\index{Sufficient command set}\index{Command set!sufficient}\index{cancel@\fmt{cancel}} \begin{figure} \begin{tabular}{rl} necessary command set $N\quad =$ & \{ \fmt{indent}, \fmt{outdent}, \fmt{force}, \fmt{break\_space}, \fmt{opt} \} \\ convenient command set $C\quad =$ & $N$ $\cup$ \{ \fmt{backup}, \fmt{big\_force} \} \\ sufficient command set $S\quad =$ & $C$ $\cup$ \{ \fmt{cancel}, \fmt{no\_indent} \} \\ \end{tabular} \caption{Naming of subsets of the command set.} \label{command-set} \end{figure} \subsection{Open Prettyprinting Problems} \label{sec:open:pp:problems} \begin{quote} ``No there isn't, and there won't be [a method of vertically aligning statements in \CWEB{}]. It is true that\CWEB{} forgets your alignment, but you should realise that it also forgets {\em any} layout feature present in your source file (e.g., line breaks). Apart from the fact that it would be very hard to integrate any alignment processing into \CWEAVE's ordinary parsing operations, it is an impossible task for \CWEAVE, since it knows nothing about the actual width of identifiers and other items. So the only possibility would be to transmit alignment instructions to \TeX, but \TeX{} typesets code in paragraph mode (breaking lines to the width of the page if necessary), and there is no way to mix that with an alignment.'' Marc van Leeuwen \cite{vanLeeuwen96:pp:control} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent If you have ever tried to use a prettyprinter for your own code you will surely have come across problems concerning user control. Yehudai states, that % \index{Prettyprinting!problems}\index{User control} \index{Yehudai, A.} % \begin{quote} ``[\dots] it is not clear that any automated indentation scheme will be adequate, as I may choose different ways to lay out the same construct in different parts of my program.'' \cite[p.~85]{Yehudai80} \end{quote} % Woodman gives an example for this point that he calls ``adaptive combs'' \cite[p.~616]{Woodman86}, where a long \res{if}/\res{elsif} statement in Modula-2 is cited as: % \index{Woodman, M.}\index{adaptive combs@``adaptive combs''} \index{Modula-2} % \begin{outp} \res{if} \id{longexpression1} \res{then}\myindent\myforce \id{longstatement1}\myoutdent\myforce \res{elsif} \id{expr2} \res{then} \id{stmt2}\myforce \res{elsif} \id{longexpression3} \res{then}\myindent\myforce \id{longstatement3}\myoutdent\myforce \res{else}\myindent\myforce \id{longstatement4}\myoutdent\myforce \res{end}\myforce \end{outp} % Here the statement \id{stmt2} appears on the ``tooth'' of the comb, whereas the context rather suggests that it should appear between the teeth like all other statements. This is a question of {\em context sensitive formatting\/} and it is an open question, how to deal with this problem in terms of format commands.\footnote{ Woodman proposes the idea of ``linked folds'', i.e.~a special set of format commands that force a number of consecutive folds to be treated equally, but doesn't elaborate on it.} \index{Tooth}\index{Context sensitive formatting} \index{Linked folds} Another open problem falls into the same domain, but deals with horizontal spacing instead of line breaking. Blaschek \cite[p.~701]{Blaschek89} points out that his system is not able to align constructs horizontally, as for example in: % \index{Horizontal spacing}\index{Spacing!horizontal}\index{Blaschek, G.} % \begin{outp} \res{with} \id{stmt} $\hat{ }$ \res{do}\myindent\myforce \begin{tabular}{ll} \id{position} & \ass\ \id{pos} \\ \id{decLabel} & \ass\ \id{label} \\ \id{next} & \ass\ \res{nil} \\ \end{tabular} \myforce \res{end}\myforce \end{outp} % This is a problem that no prettyprinter to date has mastered in an automatic fashion. It is an open question whether these problems could be solved using intelligent algorithms that learn a layout style by example, like for instance the `intelligent' prettyprinter by Winter and Cook \cite{Winter89}. But maybe the worst (and oldest) prettyprinting problem is how to typeset comments! Papers as early as those of Mohilner \cite{Mohilner78} and Jackel \cite{Jackel80} address this topic and the core of the problem surely lies in the nature of comments. The paper ``Programming languages should NOT have comment statements'' by Kaelbling \cite{Kaelbling88} and that by Grogono \cite{Grogono89} strongly argue that at last comments should be treated equally as parts of the language, not as an add-on that is forgotten at first point during compilation. Grogono brings this to the point by stating that ``Comments are second class citizens.'' \cite[p.~80]{Grogono89} They are mostly allowed anywhere in the source code and prettyprinters who want to preserve them in the output have severe problems doing that without destroying the program's format, because they have to be incorporated into the prettyprinting grammar. \index{Winter, K.}\index{Cook, C.}\index{Prettyprinter!intelligent} \index{Intelligent prettyprinter}\index{Typesetting comments} \index{Comments}\index{Prettyprinting problems!worst and oldest} \index{Mohilner, Patricia R.}\index{Jackel, M.} \index{Kaelbling, M. J.}\index{Second class citizens}\index{Equality} \index{Grogono, P.}\index{Prettyprinting grammar!and comments} There have been attempts to do this in a structured way, i.e.~to divide comments into classes and to treat each class differently \cite{Richard77,Rubin83,Fritzson83,Rorbillard89}. Rose and Welsh distinguish between pre- and postcomments and state that comments must move with the syntactic elements that they refer to \cite[p.~660]{Rose81}. Kaelbling even goes as far as to demand ``scoped comments'', i.e.~comments that explicitly show to which part of the program they belong. \index{Rose, G. A.}\index{Welsh, J.}\index{Classes of comments} \index{Comments}\index{precomments@``precomments'' (Rose and Welsh)} \index{postcomments@``postcomments'' (Rose and Welsh)} \index{Kaelbling, M. J.}\index{scoped comments@``scoped comments'' (Kaelbling)} All these attempts have the same goal, but the problem of prettyprinting comments will only be solved, if they are treated as an equal part of a programming language and thus are included in the reference grammar. % ###################################################################### \chapter{Future Work} \label{chap:future:work} \begin{quote} ``In automatic formatting one should avoid interpreting layout features of the source text unless they are so special that the user can always avoid supplying such features inadvertently (e.g., one could imagine blank lines in the program code being automatically converted to `\verb"@#"', but even there some programmers may feel that this cramps their input style). [...] it would be a good thing however if any popular layout style could be selected as an option to the prettyprinter (just like \LaTeX{} allows selection of a document style independently from its contents) [...]'' Marc van Leeuwen \cite{vanLeeuwen95:pp:layout:style} \end{quote} \index{Leeuwen@van Leeuwen, Marc} \noindent After having finally implemented and tested the \pretzel\ program I have noticed, that the program doesn't do very much at all, although it suits the specifications that belonged to this project. To enjoy beautifully formatted source code you still have to construct your prettyprinting grammar. As is seems, the work of fine tuning such a grammar that the prettyprinter is able to handle the last formatting detail you desire is quite tedious and time-consuming, especially if you start to build your grammar from scratch. But after constructing such a grammar for \PASCAL\ and applying it to a few everyday-example \PASCAL\ source codes, I was astonished how easy it was to change the looks of the prettyprinted text. I think that starting with a formal grammar of your favourite language and trying to enhance it and transform it into a prettyprinting grammar is surely a better way to reach your goal. I suppose that the \pretzel\ program could be the right tool to help you with this task. \index{Omissions}\index{Prettyprinting grammar}\index{pascal@\PASCAL} \index{pretzel@\pretzel} However, since only few people have used \pretzel\ until today there will surely be a lot of things people miss when using the program. Here are a few things I have thought of already: \begin{description} \item[Allow \t{/*}\dots\t{*/} comments.] In places where the user has an empty production in the formatted grammar file or an empty token definition in the formatted token file file, it would be nice to have a C like commenting feature with opening and closing delimiters. The `\t{//}' comment delimiter isn't nice if you want to add an attribute definition to an empty production. \index{Empty tokens}\index{-@\t{/*}\dots\t{*/} comments} \index{--@\t{//} comments} \item[Copy comments.] It surely would make the generated flex and Bison files more readable, if \pretzel\ would copy the comments from the formatted token and the formatted grammar files into them. \index{Copy comments} \item[Generate \t{\%token} definitions.] If one would impose the restriction to use only uppercase identifiers as terminal token names \pretzel\ could automalically generate the list of \t{\%token} definitions needed to identify terminals in the formatted grammar file. \index{token definitions@\t{\%token} definitions} \item[Change prettyprinting grammar format.] It would be nice to be able to insert format commands directly into the grammar rules, like for example in: \begin{inp} WHILE expr DO \fmt{indent} stmt \fmt{outdent} \fmt{force} $\longrightarrow$ stmt \end{inp} This is a point that effects fundamentals of the \id{build\_pparse} function. Other parts of \pretzel\ are not involved. This is a change that would be good for new users, since this way of specifying the grammar is much more intuitive. \index{Inituitive grammar format}\index{build pparse@\id{build\_pparse}} \index{Prettyprinting grammar} \item[Include files for grammars.] As parts of prettyprinting grammars occur frequently in many different programming languages (such as the formatting of expressions) it would be nice to be able to include files that contain these definitions with a simple command in the formatted token and formatted grammar files. On a more abstract level one could think of a notion of modules of grammars, i.e.~parts of a grammar that can be called with arguments to suit local demands (``grammar templates''?). But it is still an unanswered question whether this is practical, because of the lack of method to specify the interface of such a module. \index{Include files for grammars}\index{Prettyprinting grammar!include files} \item[Enhance \noweb{} support.] This includes managing multiple prettyprinting filters and automatically selecting a filter for the right language (if you mix languages in \noweb{} files). The \noweb{} support seems the place where the most work can be done to get a practical system. \end{description} \noindent Suggestions are always welcome. % ###################################################################### \chapter{Reference} \begin{quote} ``I used to think that prettyprinting was the cats meow, but after becoming a bit accustomed to \noweb{} I find that a \CWEB{} printout looks somewhat like gibberish.'' Barry Schwartz \cite{schwartz94:use:of:prettyprinting} \end{quote} \index{Schwartz, Barry} \noindent This chapter contains a complete and detailed reference of the \pretzel{} system. This is information that mostly is also contained in the manual pages \t{pretzel(1)} and \t{pretzel-it(1)}. \section{The Concept of Pretzel} The concept of \pretzel\ is visualized in figure \ref{concept}. From a formal formatting description of a programming language $P$, \pretzel\ generates a prettyprinting function that can be used to prettyprint source code in $P$. To get the actual prettyprinting program, you only have to supply a main program (or use the one that comes with \pretzel). If the way of prettyprinting needs to be changed, the user only needs to change formal parts in the input and use \pretzel\ again to get an enhanced prettyprinter. \index{pretzel@\pretzel!concept} \index{P@$P$} \begin{figure} \begin{center} \setlength{\unitlength}{0.012500in}% \begin{picture}(203,87)(8,744) \put( 90,789){\makebox(0,0)[b]{pretzel}} \thinlines \put( 54,744){\framebox(72,18){}} \put( 87,777){\vector( 0,-1){ 9}} \thicklines \put( 30,753){\vector( 1, 0){ 18}} \put(129,753){\vector( 1, 0){ 24}} \thinlines \put( 66,783){\framebox(45,18){}} \put( 87,819){\vector( 0,-1){ 12}} \put( 90,822){\makebox(0,0)[b]{formal description}} \put( 90,750){\makebox(0,0)[b]{prettyprinter}} \put( 18,750){\makebox(0,0)[b]{Text}} \put(183,759){\makebox(0,0)[b]{prettyprinted}} \put(177,744){\makebox(0,0)[b]{text}} \end{picture} \end{center} \caption{The concept of \pretzel.} \label{concept} \end{figure} Figure \ref{detailed-concept} on page \pageref{detailed-concept} shows the generating process in slightly more detail. The figure shows that the program \pretzel\ doesn't generate a prettyprinter immediately; what it does is to produce code that can be turned into a \CPP\ prettyprinting class with the help of two tools: % \index{c++@\CPP} % \begin{description} \item[flex] A POSIX.2 compliant lexical analyser generator. \item[Bison] A POSIX.2 compliant parser generator. The version used with \pretzel\ has to produce \CPP\ compliant source. \end{description} \index{flex}\index{Bison}\index{POSIX} \noindent Users that are already familiar with the basics of both tools will find it easier to read the following text because the way of specifying input to \pretzel\ is quite close to the ways used by them. However, this text aims at people who don't have such knowledge and will explain everything that is necessary. Also visible from this figure is that \pretzel\ creates two things: \begin{itemize} \item A prettyprinting scanner class and \item a prettyprinting parser class (containing the actual prettyprinter). \end{itemize} \index{Prettprinting scanner}\index{Prettyprinting parser} The prettyprinting parser is the actual prettyprinter function that you normally want to get when using \pretzel. The prettyprinting scanner is used by the parser and takes care of the token formatting. Both parts are separate modules with a well defined interface and can be used individually. Hence, you can write your own scanner or parser if you really need features that the ones produced by \pretzel\ don't have. \subsection{The Input Files} The word ``pretty'' is very subjective and so programming language source code can be printed in a ``pretty'' kind of fashion in almost infinitely many ways, according to the taste and preferences of the user. If the task of prettyprinting is handed over to the computer, the user must specify in detail all of his wishes towards the appearance of the output of the prettyprinter. To generate a prettyprinter, \pretzel\ needs two descriptions that it expects to find in two different files: \begin{description} \item[A formatted token file.] This file should contain all information concerning the individual formatting of tokens (i.e.~identifiers, reserved words, etc.). \item[A formatted grammar file.] This file should contain a prettyprinting grammar, i.e.~a context free grammar enhanced with formatting commands. This information is necessary to handle the more global aspects of prettyprinting that need information about the language context (i.e.~indentation, line breaks, etc.). \end{description} \index{Formatted token file}\index{Formatted grammar file} \noindent The name of the first file might be a little misleading, since it doesn't contain formatted tokens. Instead it tells you what you will get from the definitions therein. A name like ``token formatting file'' might have been a little better, but the similarity in names between the two input files sounded good and seemed to outplay this small inconsistency. The special formats of these two files are described later in section \ref{file-formats}. The interface to the generated \pretzel{} classes is described in detail in section \ref{sec:pretzel:interface}. \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/detailed-concept.latex} \end{center} \caption{The current process of generating a prettyprinter with \pretzel.} \label{detailed-concept} \end{figure} \section{The Format of the Input Files} \label{file-formats} \index{File formats} Now we turn to a vital thing for the user of \pretzel: The format of the \pretzel\ input files. Here the user has to put a formal description of the underlying programming language and (with the help of format commands) state how its text should be formatted. We have seen that \pretzel\ takes two input files: The formatted token file and the formatted grammar file. We suggest to use the suffix `{\tt .ft}' for a formatted token file and `{\tt .fg}' for a formatted grammar file. \index{ft@\t{.ft} suffix}\index{fg@\t{.fg} suffix} \index{Filename conventions}\index{Conventions} \subsection{The Formatted Token File} \index{Formatted token file} The formatted token file contains a list of token definitions with their corresponding ``prettyprinted'' form. The prettyprinted form of a token will be called an {\em attribute} or a {\em translation}. The general outline of the formatted token file is % \begin{outp} \id{declarations} \t{\%\%} \id{token definitions} \end{outp} % Normally, the {\em declarations} part is empty. You can put a general description of the file here (as a \C\ comment) and redefinitions of the default interface go here as well (see section \ref{sec:pretzel:interface} for more). The {\em token definitions} section of the formatted token file contains a series of token definitions of the form: % \begin{outp} \id{pattern}\qquad \id{token}\qquad \{\id{attribute}\} \end{outp} % The {\em pattern} must be a valid regular expression (in terms of {\tt flex}) and must be unindented. The {\em token} specifies the symbolic name of the token for the pattern and begins at the first non-whitespace character after the pattern. The token name must be a legal name for an identifier in \PASCAL\ notation and {\em must be all in upper case}. (Underlines are allowed but not at the beginning of a word.) \index{pascal@\PASCAL} The {\em attribute} for this token, that is it's prettyprinted form, consists of all text between the two curling brackets `\{' and `\}'. Attributes can be either simple strings (surrounded by double quotes) or format commands (like \fmt{force}, \fmt{indent}) or a combination of both joined together by an optional `\t{+}' sign. Attribute definitions can cover several lines and the starting `\{' needn't stand on the same line as the token definition; however subsequent lines must be indented with at least one blank or one tab. Attributes can also contain \C{} code. See section \ref{sec:adding:code} or the manual page \t{pretzel(1)} for details. % this info belongs here too XXX If you define strings as part of an attribute definition, you have to specify them in a \C\ kind of fashion, i.e.~you can insert newlines and tabs with `\verb+\n+' and `\verb+\t+'. But if you want to insert a backslash into a string, you mustn't forget to put two backslashes (`\verb+\\+') into the input file. This is especially noteworthy if you are using \TeX\ as typesetter, because \TeX\ uses a backslash as a prefix for typesetting commands. If the definition of the attribute is omitted \pretzel\ creates an attribute for this pattern by default. The default attribute consists of the string containing the text matched by the corresponding pattern. The user himself may also refer to the matched text by using the sequence `\t{**}'. Thus % \begin{verbatim} "foo" BAR "foo" BAR { ** } "foo" BAR { "foo" } \end{verbatim} % all have the same meaning. You can use a `\t{|}' sign as a token name; this signals that the current regular expression has the same token name (and also the same attribute) as the token specified in the following line (empty lines are ignored). An attribute definition behind a `\t{|}' is illegal. However you may specify regular expressions with neither a token name nor an attribute to give a default rule or to eat up whitespace. The following examples are all legal token definitions (and please note the dot in the very last line): \begin{verbatim} [0-9] DIGIT "{" OPEN { "\\{" indent force } [a-z][a-z0-9]* ID { "{\\it " + ** + "}" } "function" | "procedure" PROC_INTRO { big_force ** } [\t\ \n] | . \end{verbatim} The declarations and the token definitions must be separated by a line containing only the two characters \t{\%\%}. So the shortest possible formatted token file is % \begin{verbatim} %% \end{verbatim} % but this doesn't seem of any use, does it? \subsection{The Formatted Grammar File} \label{fg-file} \index{Formatted grammar file} In the formatted grammar file the user encodes the general prettyprinting grammar for the programming language. This is done by specifying a context free grammar of the language and by adding information about the creation of new attributes in every rule. \index{Context free grammar} The formatted grammar file is the second and last input to the \pretzel\ program. Its general outline looks like this: \begin{outp} \id{token declarations} \t{\%\%} \id{grammar rules} \end{outp} The {\em token declarations} section may be empty and the separator between the two parts of the file (\t{\%\%}) must appear unindented on a single line by itself. Before we look at these declarations, let's have a look at the grammar rules. The {\em grammar rules} section contains the collection of rules of the context free grammar that can be accompanied by an attribute definition. A rule is specified by stating the resulting token, a colon and then the series of tokens which will be reduced by this rule. The rule is ended by a semicolon. A block definition in \PASCAL\ for example might look like this: % \begin{verbatim} block : BEGIN stmt_list END ; \end{verbatim} Following the token list on the right side of the colon can be an attribute definition; this definition states, how the translation of the produced symbol is obtained from the tokens on the right side of the rule. An attribute definition is bracketed amidst curling brackets `\{' and `\}' and can again consist of strings (in double quotes) and format commands or both joined together with `\t{+}'. But here you can also refer to the attributes of the tokens on the right side of the rule. This is done in a slightly awkward notation with a number that is preceded with a `\t{\$}' dollar sign. The numbers refer to the order of appearance of the symbols on the right side of the rule. So `\t{\$1}' refers to the first token of the rule, `\t{\$2}' to the second, \dots Again attribute definitions are allowed to span several lines and strings must be specified in \C\ manner. They can also contain \C{} code as described in section \ref{sec:adding:code}. \index{c@\C} For example, here again is the possible definition of a block in \PASCAL, now with an example attribute definition: % \begin{verbatim} block : BEGIN stmt_list END { $1 + $2 + force + $3 } ; \end{verbatim} \index{pascal@\PASCAL} The attribute of a \t{block} will therefore consist of the attributes of the \t{BEGIN} and \t{stmt\_list} tokens, joined together with a \fmt{force} command and the translation of the \t{END} token. The attribute definition may be omitted. If this is so, \pretzel will by default form the attribute of the produced symbol from the simple concatenation of the attributes on the right side of the rule. For instance % \begin{verbatim} stmt : block SEMI ; \end{verbatim} % means the same as: % \begin{verbatim} stmt : block SEMI { $1 + $2 } ; \end{verbatim} Of course you may also have empty right sides of a rule (to produce things out of nothing) or simply concatenate two or more rules resulting in the same symbol with a `\t{|}'. So the following are legal rules: % \begin{verbatim} stmt_list : { force } | stmt_list stmt SEMI { $1 $2 $3 force } ; \end{verbatim} To end this subsection, we have to return to the {\em token declarations} section of the formatted grammar file. Here we have to insert a special line for every terminal token that appears in the grammar rules. These definitions are of the form `\t{\%token} \id{tokenname}'. This part of the formatted grammar file is owed to Bison and should be removed in subsequent versions. \subsection{Comments and Code} \index{Comments!in \pretzel\ input files} There is a very simple way of putting comments into the formatted token and formatted grammar files. This is done in a \CPP\ kind of manner by preceding the comment with a double slash (`\t{//}'). All characters between this sign and the end of the line are ignored by pretzel. \index{c++@\CPP} In both files you can put additional \CPP\ code before and after the definitions/grammar sections. If you want to insert code at the end of your file, you have to put a second `\t{\%\%}' on a line by itself and put the code behind it. \C/\CPP\ Code before the definitions/rules section has to be tied in with a `\%\{', `\%\}' pair. Inserting extra code is interesting for people who want to call this code from within the attribute definitions. See section \ref{sec:adding:code} for details. % should be put here XXX \section{Synopsis of \t{pretzel} and \t{pretzel-it}} \subsection{\t{pretzel-it}} The shell script \t{pretzel-it} uses \pretzel{} to build a simple prettyprinter executable. It minimizes building a \pretzel{} prettyprinter to just one shell command. You have to provide the same two input files to \t{pretzel-it} as to \pretzel. These two files are called the formatted token file (suffix \t{.ft}) and the formatted grammar file (suffix \t{.fg}). Both files need to have the same prefix. From this input, \t{pretzel-it} generates an executable prettyprinter. To get to know the options, type % \begin{verbatim} pretzel-it -h \end{verbatim} % at the command line. The full usage is: % \begin{verbatim} pretzel-it [-iqvdnh] language ppname \end{verbatim} % Here's an explanation of the options: % \begin{description} \item[-i] Don't remove intermediate products of pretzeling. \item[-q] Run quietly. \item[-v] Verbose mode, print shell commands before invoking (for debugging). \item[-d] Turn prettyprinter debugging features on by default (for debugging the prettyprinting grammar). \item[-h] Print full usage message. \item[-n] Noweb mode, will produce a prettyprinting filter \t{ppname} compatible to Norman Ramsey's \noweb{} literate programming system. The filter can be inserted into the \noweb{} pipeline using \t{noweave}'s \t{-filter} option. \end{description} % See also the manpage \t{pretzel-it} and chapters \ref{chap:using:pretzel} and \ref{chap:pretzel:meets:noweb}. \subsection{\t{pretzel}} \pretzel\ is invoked by typing % \begin{verbatim} pretzel \end{verbatim} % at the command line. The full usage of \pretzel\ can be obtained using the \t{-h} option. It is: % \begin{verbatim} pretzel [-qtgdh] [-o outfile] (prefix | file1 file2) \end{verbatim} % Here's an explanation of the options: % \begin{description} \item[-q] Run quietly (no screen output). \item[-t] Process formatted token file only. \item[-g] Process formatted grammar file only. \item[-d] Run in debug mode (i.e.~print out debugging information on the screen while running). \item[-h] Show full usage. \item[-o outfile] Names of the produced output files begin with ``outfile''. \end{description} % The options \t{-t} and \t{-g} are mutually exclusive, i.e.~you can't choose both at the same time. \index{pretzel@\pretzel!options} The command line parameters have different meanings depending on whether one ore two names are given. If there is only one parameter, it specifies the prefix of both formatted token and formatted grammar files. The suffixes `{\tt .ft}' and `{\tt .fg}' are assumed. But if there are two parameters at the command line, \pretzel\ will take the first as full name of the formatted token file and the second as full name of the formatted grammar file. In this case, the output files will get a default name. The output files will have endings `{\tt .l}' (token file) and `{\tt .y}' (grammar file). \index{ft@\t{.ft} suffix} \index{fg@\t{.fg} suffix} \index{l@\t{.l} suffix} \index{y@\t{.y} suffix} % ###################################################################### \addcontentsline{toc}{chapter}{Bibliography} \bibliographystyle{plain} \bibliography{../bibliographies/prettyprinting,../bibliographies/litprog,../bibliographies/supplemental} % ###################################################################### \addcontentsline{toc}{chapter}{Index} \printindex \end{document} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $Log: pretzelbook.tex,v $ Revision 2.1 1997/07/09 14:39:29 gaertner Updates for 2.0g: this is second edition. Cahpetr on noweb enhanced, built in info on Java prettyprinter. Revision 2.0 1996/12/16 17:41:38 gaertner finished version for 2.0 Revision 1.2 1996/12/16 13:35:15 gaertner Revised version. Only reference and future work missing. pretzel-2.0n-2/doc/pretzelbook/simpas.ft0000777000000000000000000000000010765020754025053 2../../languages/examples/simpas.ftustar rootrootpretzel-2.0n-2/doc/pretzelbook/moreverb.sty0000644000000000000000000001614106537752131017556 0ustar rootroot%%% moreverb.sty %%% AJCD 20 Sep 91 %%% adds various verbatim environments using Rainer Sch\"opf's new verbatim %%% environment. %%% Marginal hacks (RF) to work `properly' with 2e \def\filedate{1994/12/13} \def\fileversion{v2.0} % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{moreverb} [\filedate\space \fileversion\space LaTeX2e package for `more' verbatim enhancements] \typeout{Package: `moreverb' \fileversion \space <\filedate> (RF, after AJCD and RmS)} %\typeout{English Documentation \@spaces <\docdate>} % oh no there isn't %%% load verbatim style if not already loaded. \@ifundefined{verbatim@processline}{\RequirePackage{verbatim}}{} %%% verbatimwrite writes all text in its body to a file, the name of which it %%% is given as an argument. Written by RmS. \newwrite \verbatim@out \def\verbatimwrite#1{% \@bsphack \immediate\openout \verbatim@out #1 \let\do\@makeother\dospecials \catcode`\^^M\active \catcode`\^^I=12 \def\verbatim@processline{% \immediate\write\verbatim@out {\the\verbatim@line}}% \verbatim@start} \def\endverbatimwrite{% \immediate\closeout\verbatim@out \@esphack} %%% Auxiliary macros and counters for expanding tabs. Use by listing and %%% verbatimtab environments. \newcount\tab@position \newcount\tab@size \newcount\verbatimtabsize \verbatimtabsize=8 \def\@xobeytab{\leavevmode\penalty\@M {\loop\ \global\advance\tab@position-1 \ifnum\tab@position>0 \repeat}} \begingroup \catcode`\^^I=\active \gdef\@vobeytabs{\catcode`\^^I\active\let^^I\@xobeytab}% \endgroup \def\verbatim@tabexpand#1{% \ifx#1\@nil \let\next\par \else \ifx#1\@xobeysp \@xobeysp\advance\tab@position-1 \else \ifx#1\@xobeytab \@xobeytab\else #1\advance\tab@position-1 \fi\fi \ifnum\tab@position=0 \tab@position\tab@size \fi \let\next\verbatim@tabexpand \fi\next } %%% listing defines a verbatim environment with numbered lines; it takes an %%% optional argument specifying the number of lines between numbered %%% lines, and a mandatory argument specifying the starting line. listingcont %%% continues from the place where listing left off. %%% The style in which the label is set can be altered by re-defining %%% \listinglabel. * versions are provided. \newcount\listing@line \listing@line=1 \newcount\listing@step \listing@step=1 % Adding an \hbox in front of the line causes a line break, so I go % through this rigmarole to get the lines aligned nicely. I probably % missed some obvious reason why \hboxes don't work. \def\listinglabel#1{\rlap{\small\rm\the#1}\hskip2.5em} \def\thelisting@line{% \setbox0\hbox{\listinglabel\listing@line}% \@tempcnta=\listing@line \divide\@tempcnta\listing@step \multiply\@tempcnta\listing@step \ifnum\listing@line=1 \unhbox0 \else \ifnum\@tempcnta=\listing@line \unhbox0 \else \hskip\wd0 \fi\fi} \def\listing{\@ifnextchar[{\@listing}{\@listing[1]}} \def\@listing[#1]#2{% \global\listing@line=#2\global\listing@step=#1\listingcont} \def\listingcont{% \tab@size=\verbatimtabsize \def\verbatim@processline{\tab@position\tab@size \thelisting@line \global\advance\listing@line1 \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start} \let\endlisting=\endtrivlist \let\endlistingcont=\endtrivlist \@namedef{listing*}{\@ifnextchar[{\@listingstar}{\@listingstar[1]}} \def\@listingstar[#1]#2{% \global\listing@line=#2\global\listing@step=#1\relax \csname listingcont*\endcsname} \@namedef{listingcont*}{% \def\verbatim@processline{% \thelisting@line \global\advance\listing@line1 \the\verbatim@line\par}% \@verbatim\verbatim@start} \expandafter\let\csname endlisting*\endcsname =\endtrivlist \expandafter\let\csname endlistingcont*\endcsname =\endtrivlist %%% file input version of listing \def\listinginput{% \@ifnextchar[{\@listinginput}{\@listinginput[1]}} {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N \lowercase{% \gdef\@listinginput[#1]#2#3{\begingroup \global\listing@line=#2\global\listing@step=#1 \tab@size=\verbatimtabsize \def\verbatim@processline{\tab@position\tab@size \thelisting@line \global\advance\listing@line1 \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs \def\verbatim@addtoline##1~{% \verbatim@line\expandafter{\the\verbatim@line##1}}% \openin\verbtab@in=#3 \ifeof\verbtab@in\typeout{No file #3.}\else \verbtab@oktrue \loop \read\verbtab@in to \verbtab@line \ifeof\verbtab@in\verbtab@okfalse\else \expandafter\verbatim@addtoline\verbtab@line \verbatim@processline \verbatim@startline \fi \ifverbtab@ok\repeat \closein\verbtab@in\fi \endtrivlist\endgroup\@doendpe}}} %%% verbatimcmd is a verbatim environment with the exception of the escape and %%% grouping characters \, {, }. \def\verbatimcmd{% \@verbatim \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \frenchspacing\@vobeyspaces\verbatim@start } \def\endverbatimcmd{% \let\par\relax \def\verbatim@{\endtrivlist\endgroup}% \begingroup} %%% boxedverbatim produces a verbatim environment in a framed box. %%% written by Victor Eijkhout \def\boxedverbatim{% % redefine `processline' to produce only a line as wide % as the natural width of the line \def\verbatim@processline{% {\setbox0=\hbox{\the\verbatim@line}% \hsize=\wd0 \the\verbatim@line\par}}% % save the verbatim code in a box \setbox0=\vbox\bgroup \verbatim } \def\endboxedverbatim{% \endverbatim \egroup % close the box and `fbox' it \fbox{\box0}% <<<=== change here for centering,... } %%% verbatimtab is a verbatim environment which expands tab characters; it %%% takes an optional argument specifying the width of tab stops \def\verbatimtab{\futurelet\next\@verbatimtab} \def\@verbatimtab{\if\next[ \let\next\@@verbatimtab\else \def\next{\@@verbatimtab[\the\verbatimtabsize]}\fi\next} \def\@@verbatimtab[#1]{% \do@verbatimtab{#1}{% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}% } \def\do@verbatimtab#1#2{% \tab@size=#1 \def\verbatim@processline{\tab@position\tab@size \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}#2 } \let\endverbatimtab=\endtrivlist %%% file input version of verbatimtab \newread\verbtab@in \newif\ifverbtab@ok \def\verbatimtabinput{% \@ifnextchar[{\@verbatimtabinput}{\@verbatimtabinput[\the\verbatimtabsize]}} {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N \lowercase{% \gdef\@verbatimtabinput[#1]#2{\begingroup \do@verbatimtab{#1}{% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs}% \def\verbatim@addtoline##1~{% \verbatim@line\expandafter{\the\verbatim@line##1}}% \openin\verbtab@in=#2 \ifeof\verbtab@in\typeout{No file #2.}\else \verbtab@oktrue \loop \read\verbtab@in to \verbtab@line \ifeof\verbtab@in\verbtab@okfalse\else \expandafter\verbatim@addtoline\verbtab@line \verbatim@processline \verbatim@startline \fi \ifverbtab@ok\repeat \closein\verbtab@in\fi \endtrivlist\endgroup\@doendpe}}} pretzel-2.0n-2/doc/pretzelbook/pretzeldoc.sty0000777000000000000000000000000010765020754024551 2../styles/pretzeldoc.styustar rootrootpretzel-2.0n-2/doc/pretzelbook/simpas.fg0000777000000000000000000000000010765020754025021 2../../languages/examples/simpas.fgustar rootrootpretzel-2.0n-2/doc/pretzelbook/pretzelbook-1st-ed.dvi0000644000000000000000000067751006255303776021354 0ustar rootroot÷ƒ’À;è TeX output 1996.12.16:1833‹ÿÿÿÿ ½\È ýN£8 ˜G þnÿÿ’¢è-óDÓítG®G®cmr17¹The‘7tPretzelb•sŽo“okŽŸ,’¹Þ„óX«Q cmr12ºF‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸ’«ßúDecem¬rbSŽer–ê¨16,“1996ŽŽŽŒ‹* ½\È ýN£8‘63×óKñ`y cmr10²2ŽŽ ˜GŽŒ‹  ½\È ýN£8 ˜G ýÔâ‘'¿¬óÂÖN áH cmbx12ÅCon–ÿ8õten“tsŽŸ>;Å‘'¿¬óò"V cmbx10Æ1Ž‘6¿­In®9troQÇduction’2“5ŽŽ¤ #Ü‘6¿­²1.1Ž‘M¿±Do›UUPrett•¸ãyprin“ting˜the˜Pretzel˜W‘ÿ*ªa“y‘¸‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é5ŽŽ¡‘6¿­1.2Ž‘M¿±History‘x‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é6ŽŽ¡‘6¿­1.3Ž‘M¿±Ac•¸ãkno“wledgemen“ts‘ã ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é6ŽŽ©;Å‘'¿¬Æ2Ž‘6¿­Using‘ÕTPretzel’":7ŽŽ¡‘6¿­²2.1Ž‘M¿±Getting‘UUStarted‘榑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é7ŽŽ¡‘M¿±2.1.1Ž‘m¿²A–UU rst“ExampleTÀ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é7ŽŽ¡‘M¿±2.1.2Ž‘m¿²Running‘UUPretzel‘[Ö‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é9ŽŽ¡‘M¿±2.1.3Ž‘m¿²Using–UUPretzel“Output‘¸.‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é9ŽŽ¡‘6¿­2.2Ž‘M¿±Carrying‘UUOn‘Æ®‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.1Ž‘m¿²The–UUTw¸ão“Input“Files‘MŽ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.2Ž‘m¿²F–ÿ*ªormatted‘UUT“ok¸ãens‘*‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.3Ž‘m¿²Regular‘UUExpressions‘Æp‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.4Ž‘m¿²F‘ÿ*ªormatted‘UUGrammar‘퉑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é11ŽŽ¡‘M¿±2.2.5Ž‘m¿²Prett•¸ãyprin“ting–UUwith“F‘ÿ*ªormat“Instructions‘ÔI‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é12ŽŽ¡‘M¿±2.2.6Ž‘m¿²F‘ÿ*ªormatting‘UUInstructions‘iê‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é13ŽŽ¡‘6¿­2.3Ž‘M¿±W‘ÿ*ªriting›UUPrett•¸ãyprin“ting˜Grammars‘me‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é16ŽŽ¡‘M¿±2.3.1Ž‘m¿²MoGdifying–UUan“existing“grammar‘Ôo‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é17ŽŽ¡‘M¿±2.3.2Ž‘m¿²W‘ÿ*ªriting–UUa“new“Grammar“from“Scratc¸ãh‘­8‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é17ŽŽ¡‘M¿±2.3.3Ž‘m¿²Conš¸ãtext–UUF‘ÿ*ªree“v˜ersus“Con˜text“Sensitiv˜e‘X‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é18ŽŽ¡‘M¿±2.3.4Ž‘m¿²Av‘ÿqÇailable‘UUGrammars‘&m‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é19ŽŽ¡‘M¿±2.3.5Ž‘m¿²Debugging›UUPrett•¸ãyprin“ting˜Grammars‘& ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é19ŽŽ¡‘M¿±2.3.6Ž‘m¿²ExpGeriences‘¶‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é21ŽŽ¦‘'¿¬Æ3Ž‘6¿­Pretzel‘ÕTHac®9king’þPÔ23ŽŽ¡‘6¿­²3.1Ž‘M¿±Adding–UUóŒ-ø cmcsc10ÇC“²CoGde“to“the“Rules‘Fl‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é23ŽŽ¡‘M¿±3.1.1Ž‘m¿²Example–UUfor“T‘ÿ*ªok¸ãens‘)ý‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é23ŽŽ¡‘M¿±3.1.2Ž‘m¿²Example–UUfor“Grammars‘ÂΑü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é24ŽŽ¡‘M¿±3.1.3Ž‘m¿²Summary‘±I‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é25ŽŽ¡‘M¿±3.1.4Ž‘m¿²Tips–UUand“T‘ÿ*ªric¸ãks‘?n‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é26ŽŽ¡‘6¿­3.2Ž‘M¿±The–UUPretzel“In¸ãterface‘†’‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é26ŽŽ¡‘M¿±3.2.1Ž‘m¿²The›UUPrett•¸ãyprin“ting˜Scanner‘b¿‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é27ŽŽ¡‘M¿±3.2.2Ž‘m¿²The›UUPrett•¸ãyprin“ting˜P“arser‘T‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é28ŽŽ¡‘M¿±3.2.3Ž‘m¿²Example‘±R‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é29ŽŽ¡‘6¿­3.3Ž‘M¿±Building–UUa“Pretzel“prett•¸ãyprin“ter›UUb“y˜Hand‘pÓ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é29ŽŽ¡‘6¿­3.4Ž‘M¿±Obtaining–UUa“Pretzel“Prett•¸ãyprin“ting‘UUMoGdule‘鬑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é30ŽŽ¡‘M¿±3.4.1Ž‘m¿²The›UUPrett•¸ãyprin“ting˜Scanner‘b¿‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é30ŽŽ¡‘M¿±3.4.2Ž‘m¿²The›UUPrett•¸ãyprin“ting˜P“arser‘T‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é31ŽŽ¡‘6¿­3.5Ž‘M¿±Multiple–UUPretzel“MoGdules“in“the“same“Program‘”J‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é31ŽŽ¡‘6¿­3.6Ž‘M¿±Prett•¸ãyprin“ting–UUfor“non-LŸýó5‘üffóÙ“ Rcmr7±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxXians‘ñ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é32ŽŽ¡‘M¿±3.6.1Ž‘m¿²Other–UUMarkup“F‘ÿ*ªormatters‘éâ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é32ŽŽŽŸK’Ùìx3ŽŽŒ‹h ½\È ýN£8‘63ײ4’+‹Xóp®0J cmsl10ÃCONTENTSŽŽ ˜G ý„‘\3ܲ3.6.2Ž‘|3ÝGoing–UUfor“ÇHTML;î‘ü².ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é32ŽŽ©‘63ׯ4Ž‘E3ØPretzel–ÕTmeets“óßêŸ'EŽ‘ãxXŽ¡‘'¿¬to–'6start,‘[®maš¸ãybGe“just“a“sligh˜t“idea“of“what“kind“of“things“regular“expressions“andŽ¡‘'¿¬conš¸ãtext–3îfree“grammars“are,‘:what“prett˜yprin˜ting“is“abGout“and“ho˜w“y˜our“source“coGdeŽ¡‘'¿¬lo•Goks›UUb“est˜in˜a˜prett•¸ãyprin“ted˜w“a“y‘ÿ*ª.ŽŸ"Y.‘'¿¬Ì2.1Ž‘L¦Getting‘ffStartedŽŸYõ‘'¿¬²This–ƒÐsection“will“givš¸ãe“a“ rst“in˜troGduction“to“using“Pretzel.‘ý8It“will“sho˜w“ho˜w“toŽ¡‘'¿¬build–7§a“prett•¸ãyprin“ter–7§for“a“simple“programming“language,‘=–whic¸ãh“will“bGe“a“subset“ofŽ¡‘'¿¬standard–ŽÄÇP‘ÿ ascal².‘After“reading“this“section“and“doing“the“excercises,‘y¸ãou“will“bGeŽ¡‘'¿¬able–û3to“build“arbitrary“prett•¸ãyprin“ters–û3from“the“ready-to-go“input“ les“included“inŽ¡‘'¿¬the–UUPretzel“distibution.ŽŸE ‘'¿¬ó"ÂÖN  cmbx12Í2.1.1Ž‘Pÿ¬A–€ rst“ExampleŽŸè.‘'¿¬²The–Á•input“to“Pretzel“will“alw•¸ãa“ys–Á•bGe“ó#ý': cmti10Îtwo“² les.‘¶‡Let's“start“with“these“ les“ rst“andŽ¡‘'¿¬loGok–tat“Pretzel“in“action.‘&­So“yš¸ãou“migh˜t“startup“y˜our“computer,‘¡in˜v˜ok˜e“y˜our“fa˜v˜ouriteŽ¡‘'¿¬text–Peditor“and“create“t•¸ãw“o–P les“called“Èsimpas.ft“²and“Èsimpas.fg².‘pThe“suxes“È.ftŽ¡‘'¿¬²and–Ù˜È.fg“²are“the“extensions“that“Pretzel“expšGects“for“its“input“ les.‘þBut“b˜efore“w¸ãeŽ¡‘'¿¬learn–UUabGout“what“they“stand“for,“ ll“in“the“ les“with“the“follo¸ãwing“information:Ÿü^ÿ±1ŽŽŽ¦‘'¿¬È/*–?ýsimpas.ft“--“a“simple“pretzel“example“*/Ž¡¡‘'¿¬%%Ž¡¡‘'¿¬";"‘>ÿÜSEMIŽ¡‘'¿¬"="‘>ÿÜ|Ž‘'¿¬Ÿ2’‰ff‰¬Ÿ J=‘ "5Ÿý-:ó¹Aa¨cmr6¼1ŽŽŽ‘LÜó|{Ycmr8»Y‘ÿJªou–QKcan“spare“yšÃŽourself“from“t˜yping“the“data“if“y˜ou“loÿÜ|ޤ ‘63×">"‘>ÿÜ|Ž¡‘63×"<="‘9¿ß|Ž¡‘63×">="‘9¿ß|Ž¡‘63×":="‘9¿ßBINOPŽ¡‘63×"if"‘9¿ßIFŽ¡‘63×"then"‘/?åTHENŽ¡‘63×"else"‘/?åELSEŽ¡‘63×"begin"‘)ÿèBEGŽ¡‘63×"end"‘4âENDŽ¡‘63×[0-9]+‘/?åNUMŽ¡¡‘63×[a-zA-Z][a-zA-Z0-9]*‘ÿôIDŽ¡¡‘63×[\t\–?ý\n]‘$¿ë//“eat“up“whitespaceޤjå‘E3ײHere's–UUthe“second“ le,“whic¸ãh“should“bGe“called“Èsimpas.fg²:Ž¡‘63×È/*–?ýsimpas.fg“--“a“simple“pretzel“example“*/ޤ ¡‘63×%token–?ýSEMI“BINOP“IF“THEN“ELSE“BEG“END“NUM“IDŽ¡¡‘63×%%Ž¡¡‘63×stmt_list–?ý:“stmtŽ¡‘63×|–?ýstmt_list“SEMI“stmt‘$¿ë{“$1“$2“force“$3“}Ž¡‘63×;Ž¡‘63×stmt‘ÿô:–?ýIF“exp“THEN“stmt‘4â{“$1“"“$"“$2“"$“"“$3“"“"“indent“$4Ž¡’ý³eoutdent‘?ý}Ž¡‘`3¿|–?ýIF“exp“THEN“stmt“ELSE“stmtŽ¡’ó3k{–?ý$1“"“$"“$2“"$“"“$3“indent“forceŽ¡’ý³e$4–?ýoutdent“forceŽ¡’ý³e$5–?ýindent“force“$6“outdent“force“}Ž¡¡‘`3¿|–?ýBEG“stmt_list“END‘/?å{“$1“"“"“$2“"“"“$3“}Ž¡‘`3¿|–?ýexp‘?ñ{“"$"“$1“"$"“}Ž¡‘63×;Ž¡‘63×exp‘?ñ:‘?ýIDŽ¡‘`3¿|‘?ýNUMŽ¡‘`3¿|–?ýexp“BINOP“expŽ¡‘63×;Ž©jå‘E3ײThe–ØYlanguage“that“is“co•¸ãv“ered›ØYb“y˜these˜ rst˜Pretzel˜spGeci cations˜is˜ÇP‘ÿ ascal˜²withŽ¡‘63×simple–{‡expressions“of“the“form“ó  b> cmmi10µa–Áó !",š cmsy10¸“µb–{‡²or“µa–Á²=“µb–{‡²(yš¸ãou“can“see“whic˜h“opGerators“are“al-Ž¡‘63×lo•¸ãw“ed–õœfrom“the“Èpascal.ft“² le).‘QßAlso,‘Áthe“only“statemenš¸ãts“allo˜w˜ed“are“assignmen˜ts,Ž¡‘63×the‘ÃlÆifŽ‘ x¿²-ÆthenŽ‘…N²-construct–Ãland“the“compGound“statemenš¸ãt“(i.e.“statemen˜ts“enclosed“withinŽ¡‘63ׯbQÇeginŽ‘T«í²and‘(ÆendŽ‘4‹²).‘bµSo–(the“folloš¸ãwing“(not“prett˜yprin˜ted)“coGde“w˜ould“bGe“v‘ÿqÇalid“in“theseŽ¡‘63×terms:Ÿü^ÿ±2ŽŽŽ¦‘63×Èif–?ýa=1“then“b:=1;Ž¡‘63×if–?ýa<=1“then“begin“b:=2“end“else“b:=aŽ‘63ן /‰ff‰¬Ÿ J=‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»Of–ácourse“yšÃŽou“can't“do“m˜uc˜h“with“this“\language",‘>“but“remem˜band“lea•¸ãv“e–Gºan“executable“called“Èsimpaspp².˜This“ le“is“the“prett•¸ãyprin“terŽ¡‘'¿¬for–UUthe“spGeci ed“language!Ž¡‘6¿¬By–±Zdefault,‘[the“prett•¸ãyprin“ter–±Zreads“text“from“the“standard“input“and“writesŽ¡‘'¿¬formatted–%coGde“to“the“standard“output.‘±6So“try“to“feed“the“small“example“to“theŽ¡‘'¿¬program–UUand“loGok“what“it“returns:ޤΑ'¿¬Èsimpaspp‘?ýŸ'EŽ‘ãxX“coGde“that“yš¸ãou“can“use“within“y˜our“o˜wn“doGcumen˜ts.ŽŸ\€‘'¿¬Í2.1.3Ž‘Pÿ¬Using–€Pretzel“OutputŽŸuT‘'¿¬²There's–fEa“small“doGcumen¸ãt“prepared“to“demonstrate“the“use“of“Pretzel“output“inަ‘'¿¬y•¸ãour›UUo“wn˜doGcumen“ts.‘qÇIt's˜the˜ le˜Èexample-frame.tex².ޤU‘'¿¬È\documentclass{article}ަ‘'¿¬\usepackage{pretzel-latex}ަ‘'¿¬\begin{document}ަ¦‘'¿¬This–?ýis“a“small“example“produced“by“Pretzel“and“formatted“with“\LaTeX{}.ަ¦‘'¿¬\begin{ppcode}ަ‘2?¦\input{small-example.tex}ަ‘'¿¬\end{ppcode}ަ¦‘'¿¬\end{document}Ž¡‘6¿¬²If–‡oyš¸ãou“sa˜v˜e“the“output“of“the“prett˜yprin˜ter“Èsimpaspp“²in“a“ le“b˜y“redirectingަ‘'¿¬the–K¯standard“output“(let's“call“this“ le“Èsmall-example.tex²)“and“run“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“on“theަ‘'¿¬frame,–UUthe“resulting“došGcumen¸ãt“will“lo˜ok“something“lik¸ãe“this:Ž¡‘1¿­if›UUµa–Dz=“1˜then˜µb“²:=“1;ަ‘1¿­if›UUµa–Ç<²=“1˜thenަ‘;¿®bGegin›UUµb–Dz:=“2˜endަ‘1¿­elseަ‘;¿®µb–Dz:=“µaަ¡‘6¿¬²Noš¸ãw–§what“do“y˜ou“think“of“this?‘оIs“it“what“y˜ou“expGected?‘оIt“is“ob˜vious“thatަ‘'¿¬this–;¤is“the“cošGde“that“has“b˜een“input“to“the“prett•¸ãyprin“ter.‘$³But–;¤it“is“not“ob¸ãvious,ަ‘'¿¬hoš¸ãw–Ithe“output“correspGonds“to“the“information“written“do˜wn“in“the“t˜w˜o“input“ lesަ‘'¿¬to–70Pretzel.›YThis“will“bGe“the“sub‘Ž8ject“of“the“next“subsection.˜But,–o§alas,“y•¸ãou‘70ha“v“eަ‘'¿¬w•¸ãork“ed›ïÀy“our˜w“a“y˜through˜this˜ rst˜section˜and˜kno“w˜no“w,‘ho“w˜to˜use˜Pretzel˜in˜it'sަ‘'¿¬simplest‘UUw•¸ãa“y‘ÿ*ª.ŽŽŽŒ‹ nÒ ½\È ýN£8‘63ײ10’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜G ý„‘63×Ì2.2Ž‘[:Carrying‘ffOnŽŸç‘63ײThis–Àsection“will“shoš¸ãw“y˜ou“ho˜w“the“basic“prett˜yprin˜ting“methoGd“w˜orks“that“Pretzelޤ ‘63×uses.‘MŸAfter–óòreading“this“section“y¸ãou“will“bGe“able“to“understand“roughly“what“theŽ¡‘63×con•¸ãten“ts–Àof“Pretzel“input“ les“mean“and“ho¸ãw“to“moGdify“existing“input“ les“to“goŽ¡‘63×with–UUy¸ãour“wishes.Ž©®À‘63×Í2.2.1Ž‘_s×The–€Tw o“Input“FilesŽŸuT‘63ײThe› %prett•¸ãyprin“ting˜methoGd˜used˜b“y˜a˜Pretzel˜prett“yprin“ter˜is˜quite˜simple.‘XbIt˜readsŽ¡‘63×the–ýÕinput,›'ôwhic¸ãh“usually“is“the“plain“source“coGde,˜cuts“this“text“in¸ãto“small“piecesŽ¡‘63×called–¥(Îtokens²,‘¹and“tries“to“rearrange“them“in“suc¸ãh“a“fashion“that“the“user“will“callŽ¡‘63×sthetic.‘˜[Of–b1course,‘¥hthe“relativš¸ãe“order“of“the“input“tok˜ens“will“(usually)“not“bGeŽ¡‘63×cš¸ãhanged,‘=Kbut–çthe“amoun˜t“of“whitespace“in˜bGet˜w˜een“migh˜t“bGe“enlarged“or“reduced,Ž¡‘63×line–eãbreaks“ma¸ãy“bšGe“inserted“at“sp˜ecial“places“etc.‘£rAll“this“is“sp˜eci ed“b¸ãy“rules“thatŽ¡‘63×the–±|user“writes.‘†implemenš¸ãt“a“simple“prett˜yprin˜ter,‘8w˜e“w˜ould“only“need“to“spGecify“the“patternsŽ¡‘63×for–^šthe“tok¸ãens“and“add“some“information,‘`ëwhat“the“output“device“should“do“if“thisŽ¡‘63×pattern–X™can“bGe“matcš¸ãhed.‘{“An“example“will“sho˜w,›™jthat“this“is“not“enough,˜if“y¸ãouŽ¡‘63×strivš¸ãe–UUfor“full“user“con˜trol“o˜v˜er“prett˜yprin˜ting.ަ‘E3×F‘ÿ*ªor–UUexample“lošGok“at“the“follo¸ãwing“ÇP‘ÿ ascal“²co˜de“fragmen¸ãt.ŽŸFÔ‘@3ØÆifŽ‘J>€µi–Ç>“²1‘UUÆthenŽ‘/øµi‘Ž0²:=Ž‘ヵi–8ณ²1;ަ‘@3ØÆifŽ‘J>€µb–Ǹ“µi‘UUÆthenŽŽ¦‘J3Ùµb‘Dz:=Ž‘kµb–8à²+“1ަ‘@3ØÆelseŽ‘UÎ×µb‘Dz:=Ž‘kµb–8ณ²1;ަŸ8©‘E3×Saš¸ãy–é»the“user“w˜an˜ts“the“ rst“statemen˜t“(an“ÆelseŽ‘/e²-less“ÆifŽ‘ Ÿ²)“to“bGe“prett˜yprin˜ted“with-Ž¡‘63×out–zSa“forced“line“break“bGehind“the“ÆthenŽ‘yô²k•¸ãeyw“ord–zSand“the“second“statemen¸ãt“(a“simpleŽ¡‘63ׯifŽ‘<é*²-ÆthenŽ‘…N²-ÆelseŽ‘Eª²)–QÍto“ha•¸ãv“e–QÍa“line“break“bGehind“the“k•¸ãeyw“ords–QÍand“additional“inden¸ãtationŽ¡‘63×to–­âthe“statemenš¸ãts“to“enhance“readabilit˜y‘ÿ*ª.‘9öThis“is“hardly“expressible“in“terms“of“\for-Ž¡‘63×matted–ICtokš¸ãens",‘K­bGecause“it“w˜ould“bGe“necessary“to“go“bac˜k“in“the“output“and“insertŽ¡‘63×a–ƒÙline“break“within“material“that“mighš¸ãt“ha˜v˜e“already“bGeen“output“to“the“screen“orŽ¡‘63×to‘UUpapGer.ަ‘E3×T‘ÿ*ªo–=spGecify“this“distinction“yš¸ãou“ha˜v˜e“to“tell“the“prett˜yprin˜ter“something“abGoutŽ¡‘63×what‘ñÁÆifŽ› §²-ÆthenŽ‘…N²s–ñÁare“in“di erence“to“ÆifŽ˜²-ÆthenŽ‘…N²-ÆelseŽ‘Eª²s.‘P–That's“where“the“formatted“gram-Ž¡‘63×mar–UUcomes“in¸ãto“action.ަ‘E3×If–ùqy¸ãou“lošGok“at“the“Èsimpas.fg“²example“ab˜o•¸ãv“e,‘ Òy“ou'll–ùqnotice“t•¸ãw“o–ùqrules“that“handleŽ¡‘63×these›UUt•¸ãw“o˜di eren“t˜cases.‘qÇHere˜are˜b•Goth˜rules˜again˜to˜lo“ok˜at:ŽŸ8ª‘63×Èstmt‘ÿô:–?ýIF“exp“THEN“stmt‘4â{“$1“"“$"“$2“"$“"“$3“"“"“indent“$4Ž¡’ý³eoutdent‘?ý}Ž¡‘`3¿|–?ýIF“exp“THEN“stmt“ELSE“stmtŽ¡’ó3k{–?ý$1“"“$"“$2“"$“"“$3“indent“forceŽ¡’ý³e$4–?ýoutdent“forceŽ¡’ý³e$5–?ýindent“force“$6“outdent“force“}Ž¡‘63×;ŽŸ8©‘E3ײThe–Ksecond“line“is“more“inš¸ãteresting“at“the“momen˜t:‘lªit“means“that“an˜y“ÈIF‘K²tok˜enŽ¡‘63×follo•¸ãw“ed›½b“y˜Èexp²,–uÈTHEN²,˜Èstmt²,“ÈELSE‘©²and˜Èstmt˜²tok¸ãens˜will˜bGe˜reduced˜again˜to˜a˜ÈstmtŽ¡‘63ײtok•¸ãen.‘ÖÕThe›!¯attac“hed˜description˜in˜curled˜braces˜tells˜the˜prett“yprin“ter˜to˜insertŽ¡‘63×a–åèforced“line“break“(Îfor–ÿ}'c“eŽ‘R̲)“bGehind“the“ÈTHEN‘åòtok¸ãen“if“this“rules“ res.‘#Additionally‘ÿ*ª,Ž¡‘63×the–Xstatemenš¸ãt“follo˜wing“the“ÈTHEN‘Wϲshould“ha˜v˜e“a“little“more“inden˜tation“bGefore“itŽ¡‘63×(ÎindentŽ‘Jú²)–æwhicš¸ãh“should“bGe“tak˜en“bac˜k“afterw˜ards“(ÎoutdentŽ‘!gi²).‘%wThe“same“is“spGeci edŽ¡‘63×for–Jûthe“second“statemenš¸ãt“follo˜wing“the“ÈELSE‘Jø²tok˜en.‘nTWhat“is“done“here“is“to“spGecifyŽŽŽŒ‹ ž‡ ½\È ýN£8‘'¿¬Ã2.2.‘ÇCARR‘ÿ*ªYING‘UUON’þV²13ŽŽ ˜G ý„‘'¿¬something–kšlikš¸ãe“an“attac˜hmen˜t“(or“spGecial“attribute)“of“the“tok˜en“whic˜h“this“ruleޤ ‘'¿¬reduces–4bto“(i.e.“the“Èstmt“²tokš¸ãen“on“the“left“hand“side).‘fËThis“attac˜hmen˜t“can“use“theŽ¡‘'¿¬attac•¸ãhmen“ts–Z2of“the“tokš¸ãens“on“the“righ˜t“hand“side“b˜y“referring“to“the“sequence“n˜um˜bGerŽ¡‘'¿¬in–¼ whicš¸ãh“they“appGear“there.‘>¯This“means“that“È$1“²references“the“attac˜hmen˜t“of“the“ÈIFŽ¡‘'¿¬²tokš¸ãen,‘.+È$2–$a²the“attac˜hmen˜t“of“the“Èexp“²tok˜en“and“so“on.‘avAll“the“attac˜hmen˜ts“bGet˜w˜eenŽ¡‘'¿¬the–ùÀcurled“braces“are“put“together“and“form“the“attac•¸ãhmen“t–ùÀof“the“newly“formedŽ¡‘'¿¬tokš¸ãen–ÀK(the“Èstmt“²tok˜en).‘²«Apart“from“referring“to“the“attributes“of“existing“tok˜ens,Ž¡‘'¿¬yš¸ãou–‚Åcan“additionally“insert“spGecial“formatting“instructions“(lik˜e“ÎindentŽ‘Í¿²,‘Ž!ÎoutdentŽ‘(xO²orŽ¡‘'¿¬Îfor–ÿ}'c“eŽ‘=x²)–;fand“strings“(likš¸ãe“the“È"‘?ý$"²)“in˜to“the“sequence“as“\extra"“attac˜hmen˜ts.‘#ûAllŽ¡‘'¿¬these›UUattac•¸ãhmen“ts˜together˜form˜the˜attribute˜of˜the˜new˜Èstmt˜²tok“en.Ž¡‘6¿¬The–M"spšGecial“commands“that“ha•¸ãv“e–M"app˜eared“ab˜o•¸ãv“e,‘NÆe.g.–M"the“ÎindentŽ‘"å>²or“Îfor–ÿ}'c“eŽ‘í²com-Ž¡‘'¿¬mands,‘ókare–ÓÍcalled“Îformat›Ac‘ÿ}'ommands“²or“Îformatting˜instructions².‘í/Subsequen¸ãtly“theŽ¡‘'¿¬prett•¸ãyprin“ting–ˆmethoGd“used“bš¸ãy“Pretzel“prett˜yprin˜ters“is“called“Îpr‘ÿ}'ettyprinting‘2TwithŽ¡‘'¿¬format‘˜Ic‘ÿ}'ommands².‘€The–Zmain“assumption“is“that“wš¸ãe“ha˜v˜e“a“text“formatter“at“handŽ¡‘'¿¬that–Óµuses“Îc–ÿ}'ontr“ol‘+se“quenc“es–Óµ²(or“Îtags²)“inside“the“actual“text“b•Go“dy–Óµfor“spGecifying“allŽ¡‘'¿¬di eren•¸ãt›ÈŒw“a“ys˜of˜formatting˜(suc“h˜as˜fon“ts,›åYinden“tation,˜spacing,˜alignmen“t).‘ËkAn-Ž¡‘'¿¬other–Ǭterm“for“this“w•¸ãa“y–Ǭof“formatting“is“Îin-text›èpr–ÿ}'o“c“e“dur“al˜markup–Ǭ²and“systemsŽ¡‘'¿¬using– this“tec¸ãhnique“are“commonly“called“Îdo–ÿ}'cument‘<c“ompilersŸü^ÿ±4ŽŽ‘|s².‘•ùThe– idea“bGehindŽ¡‘'¿¬the›ò0prett•¸ãyprin“ting˜methoGd˜presen“ted˜here˜is˜to˜systematically˜insert˜spGecial˜format-Ž¡‘'¿¬ting–8instructions“inš¸ãto“the“source“coGde“whic˜h“are“left“to“a“t˜ypGesetter“to“in˜terpret.Ž¡‘'¿¬The–Çùhistory“bšGehind“this“metho˜d“and“the“details“of“the“algorithm“are“explained“inŽ¡‘'¿¬the–öspGecial“cš¸ãhapter“\On“Prett˜yprin˜ting"“(c˜hapter“5).‘TF‘ÿ*ªrom“no˜w“on,‘Nsimply“thinkŽ¡‘'¿¬of–†formatting“instructions“as“actions“that“will“bšGe“p˜erformed“on“the“t¸ãyp˜eset“outputŽ¡‘'¿¬bšGefore–UUit“app˜ears“on“the“screen“or“on“pap˜er.ŽŸùñ‘'¿¬Í2.2.6Ž‘Pÿ¬F‘þàormatting‘€InstructionsޤuT‘'¿¬²No•¸ãw,›UUw“e'll˜ha“v“e˜a˜loGok˜at˜the˜formatting˜instructions˜that˜Pretzel˜o ers.ŽŸùñ‘'¿¬ÆCon•®9trolling‘ÕTInden“tationŽ¡‘'¿¬²W‘ÿ*ªe›TVha•¸ãv“e˜met˜three˜formatting˜instructions˜already:‘ñHÎindentŽ‘ Consider“for“example“a“long“bloGc˜k“ofŽ¡‘63×statemenš¸ãts–íin“ÇP‘ÿ ascal“²that“con˜tain“extremely“long“names“for“iden˜ti ers“as“in“theŽ¡‘63×follo¸ãwing‘UUexample:ަ‘@3ØÈbegin‘?ýstring_buffer[string_buffer_pointer]:=c;Ž¡‘@3Østring_buffer_pointer:=string_buffer_pointer–?ý+“1;“end;ަ‘63ײW‘ÿ*ªe–don't“w•¸ãan“t–line“breaks“to“appGear“within“idenš¸ãti ers“and“w˜e“don't“w˜an˜t“thingsŽ¡‘63×likš¸ãe–UUthis“to“crop“up“when“prett˜yprin˜ting:ަ‘@3ØÆbQÇeginŽ‘^Ù$Îstring‘‰ffŽ‘®bu erŽ’•p²[Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ‘XÎÖ²]‘Ç:=ŽŽ‘kÎcŽ‘F¸²;‘ª¨Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽŽ¡‘Búð²:=ŽŽ‘PPCÎstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’«Wù²+‘8à1;‘UUÆendŽ‘aÁ²;ަ‘63×Here,‘uÐa–<statemenš¸ãt“is“brok˜en“across“t˜w˜o“lines,‘uÐbut“w˜e“w˜ould“prefer“line“breaks“toŽ¡‘63×ošGccur–HÊonly“b˜et•¸ãw“een›HÊt“w“o˜adjacen“t˜statemen“ts˜(and˜usually˜also˜bGefore˜the˜ÆendŽ‘U6²)˜lik“eŽ¡‘63×in:ަ‘@3ØÆbQÇeginŽ‘^Ù$Îstring‘‰ffŽ‘®bu erŽ’•p²[Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ‘XÎÖ²]‘Ç:=ŽŽ‘kÎcŽ‘F¸²;Ž¡‘@3ØÎstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’›ÉƲ:=ŽŽ’©Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’&ϲ+‘8à1;Ž¡‘@3ØÆendŽ‘R@D²;ަ‘63×So–×Éthe“conclusion“is,‘ðåthat“wš¸ãe“ha˜v˜e“to“tell“the“formatter,‘ðåwhere“it“is“pGossible“to“breakŽ¡‘63×a–7zline,‘pif“the“currenš¸ãt“bloGc˜k“of“text“should“exceed“the“righ˜t“margin.‘7This“is“doneŽ¡‘63×with–Ôthe“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ›8®‚²primitiv¸ãe.‘íÉBy“inserting“a“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ˜²amidst“t•¸ãw“o‘Ôstatemen“tsŽ¡‘63×(and–‡úev¸ãen“after“the“ÆbQÇeginŽ‘"_ë²and“bšGefore“the“ÆendŽ‘”f²)“the“ab˜o•¸ãv“e–‡úproblem“cannot“happ˜enŽ¡‘63×anš¸ãy–Ÿemore.‘O÷A‘ŸRÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘8E9²tells“the“t˜ypšGesetter,‘±éto“break“a“line“at“this“p˜oin¸ãt,‘±éif“he“isŽ¡‘63×loGoking–UUfor“a“place“to“break“somewhere“near“it.Ž¡‘E3×But–bevš¸ãen“no˜w,‘¶ùa“single“statemen˜t“migh˜t“bšGe“to˜o“long“to“ t“on¸ãto“one“line.‘/ÌConsiderŽ¡‘63×for–W(example“a“ÆwhileŽ‘±Ê²-loGop“or“an“ÆifŽ‘ {²-statemenš¸ãt“with“a“v˜ery“long“expression“that“go˜v˜ernsŽ¡‘63×it,–UUas“in:ަ‘@3ØÈwhile›?ý(str‘¡E‰ff&fŽ–Ç«buf[str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr]<>c)˜and˜(str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr<=buf‘¡E‰ff&fŽ“size)˜doަ‘63ײInserting‘ËÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘4M²s–ËbšGefore“and“after“the“\Èand²"“w¸ãould“seem“to“b˜e“a“go˜o˜d“solutionŽ¡‘63×to–1Tthis“line-breaking“problem.‘ÃBut“breaking“the“line“after“the“\Èand²",–hSsaš¸ãy‘ÿ*ª,“w˜ouldŽ¡‘63×result‘UUinŽŽŽŒ‹Áy ½\È ýN£8‘'¿¬Ã2.2.‘ÇCARR‘ÿ*ªYING‘UUON’þV²15ŽŽ ˜G ý„‘1¿­ÆwhileŽ‘Oo¤²(Îstr‘‰ffŽ‘®bufŽ‘uÚ²[Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘-¿F²]–ǵ<>“ÎcŽ‘ñe²)‘UUÆandŽŽ¤ ‘1¿­²(Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘0†^¸‘ÇÎbuf‘‰ffŽ‘®sizeŽ‘$0²)‘UUÆdoŽŽ©_c‘'¿¬²what–üQof“course“is“inš¸ãtolerable.‘TW‘ÿ*ªe“w˜an˜t“a“long“con˜tin˜uous“line“to“bGe“inden˜ted“a“littleŽ¡‘'¿¬if–QIit“is“brokš¸ãen,‘Rbut“the“amoun˜t“of“inden˜tation“for“the“con˜tin˜uing“line“m˜ust“bGe“moreŽ¡‘'¿¬as–“›the“\normal"“indenš¸ãtation“of“con˜trolled“statemen˜ts“inf“conditionals“for“example.Ž¡‘'¿¬This–¹Ldistinction“visually“separates“adjacenš¸ãt“(and“inden˜ted)“statemen˜ts“from“a“singleŽ¡‘'¿¬statemenš¸ãt–¾that“ lls“t˜w˜o“lines.‘«ñT‘ÿ*ªo“this“e ect,‘Øthe“line“Îhas“²to“bšGe“brok¸ãen“around“this“p˜oin¸ãt.Ÿü^ÿ±5ŽŽ‘ÿö²So“the“ÎoptŽ‘4¯²command“denotes“anŽ¡‘'¿¬optional–úLline“break“with“the“con•¸ãtin“uation–úLline“inden¸ãted“a“little“more“with“respGect“toŽ¡‘'¿¬the–UUnormal“inden¸ãtation.Ž¡‘6¿¬So–UUin“the“example“wš¸ãe“therefore“sa˜y:ަ‘1¿­Èwhile›?ý(str‘¡E‰ff&fŽ–Ç«buf[str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr]<>c)˜and˜Îopt4Ž‘‚ËÈ(str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr<=buf‘¡E‰ff&fŽ“size)˜doŽ¡‘1¿­ÎindentŽ‘SJ¤for–ÿ}'c“eŽ‘mÝmÈbegin‘?ý...Îfor–ÿ}'c“eŽ‘’ÉÈendަ‘'¿¬²depGending–u˜on“whether“wš¸ãe“rather“lik˜ed“a“line“break“bGefore“or“after“the“\Èand²".‘ÒThisŽ¡‘'¿¬wš¸ãould–UUthen“yield“the“correct“w˜a˜y“of“formatting,“as“in:ަ‘1¿­ÆwhileŽ‘Oo¤²(Îstr‘‰ffŽ‘®bufŽ‘uÚ²[Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘-¿F²]–ǵ<>“ÎcŽ‘ñe²)‘UUÆandŽŽ¡‘O¿°²(Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘0†^¸‘ÇÎbuf‘‰ffŽ‘®sizeŽ‘$0²)‘UUÆdoŽŽ¡‘;¿®bQÇeginŽ‘W¥².–ªª.“.Ž¡‘;¿®ÆendŽŽ¦‘'¿¬²Note›þkho•¸ãw“ev“er˜that˜a˜Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘9X²is˜alw“a“ys˜a˜bGetter˜place˜to˜break˜a˜line˜than˜anŽ¡‘'¿¬optional–UUline“break“denoted“b¸ãy“ÎoptŽ‘Óˆ².ŽŸÛ£‘'¿¬ÆAdditional‘ÕTCommandsŽŸuT‘'¿¬²The–N-list“of“format“commands“is“not“y¸ãet“complete.‘odThere“are“still“a“few“more“prim-Ž¡‘'¿¬itivš¸ães–L£to“learn,‘Šwbut“they“are“not“as“impGortan˜t“as“the“other“commands“that“w˜ereŽ¡‘'¿¬presenš¸ãted–k‡up“to“this“pGoin˜t.‘´^The“follo˜wing“primitiv˜es“w˜ere“in˜troGduced“to“ac˜hiev˜eŽ¡‘'¿¬bšGetter–UUformatting“results“in“sp˜ecial“situations.Ž¡‘6¿¬The–ŸI rst“one“is“called“Îb‘ÿ}'ackupŽ‘"ÀÒ²and“denotes“a“little“negativš¸ãe“horizon˜tal“space.‘5ThisŽ¡‘'¿¬command–hmš¸ãust“bGe“preceded“b˜y“a“Îfor–ÿ}'c“eŽ‘Y4²,‘2¬bšGecause“it“do˜esn't“makš¸ãe“sense“to“bac˜kupŽ¡‘'¿¬within–ÇÛa“line“if“it's“bšGeginning“has“already“b˜een“output.‘ÉZSo“the“t•¸ãw“o‘ÇÛcommandsŽ¡‘'¿¬\Îfor–ÿ}'c“eŽ‘R̲,‘AÃÎb‘ÿ}'ackupŽ‘!IJ"–zappšGearing“in“a“ro¸ãw“can“b˜e“seen“as“a“short“form“for“the“sequenceŽ¡‘'¿¬\ÎoutdentŽ‘!gi²,‘»Îfor–ÿ}'c“eŽ‘ ã²,‘»ÎindentŽ‘ ²".‘eþThe‘¦½Îb‘ÿ}'ackupŽ‘$Ϻ²command–¦½is“used“in“cases“where“statemen¸ãtsŽ¡‘'¿¬are–Õ“preceded“bš¸ãy“labGels“or“simply“where“a“line“should“stic˜k“out“to“the“left“a“bit“inŽ¡‘'¿¬order–UUto“emphasize“it.Ž¡‘6¿¬The–È­next“additional“command“is“called“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘* ʲ.‘ËÏAs“the“name“implies“thisŽ¡‘'¿¬primitivš¸ãe–-acts“lik˜e“a“Îfor–ÿ}'c“eŽ‘iù²,‘G¢but“on“a“bigger“scale.‘·NÎbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘0˜²not“only“forces“a“lineŽ¡‘'¿¬break;‘ãit–³×also“inserts“a“little“extra“v¸ãertical“space“after“the“break.‘NY‘ÿ*ªou“can“use“theŽ¡‘'¿¬Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘PÔ5²primitivš¸ãe–Ïlto“separate“t˜w˜o“adjacen˜t“lines“that“seman˜tically“do“not“bGelongŽ¡‘'¿¬together,–UUlikš¸ãe“t˜w˜o“function“declarations.Ž¡‘6¿¬If–RWyš¸ãou“are“trying“to“t˜ypGeset“ÇC“²or“ÇCŸÿ²++Ž‘à“programs,‘‘—y˜ou“will“need“a“feature“toŽ¡‘'¿¬t¸ãypšGeset–GGso“called“prepro˜cessor“directiv¸ães.‘mThese“are“commands“b˜eginning“with“a“#Ž¡‘'¿¬that–+can“in uence“the“source“cošGde“b˜efore“compilation.‘c°Normally“these“lines“app˜earŽ¡‘'¿¬bGeginning–ò†at“the“left“margin“so“wš¸ãe“w˜an˜t“a“command“that“can“bGe“used“to“t˜ypGesetŽ‘'¿¬ŸÞ‰ff‰¬Ÿ J=‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»In–mâT‘þ•AŸ¸ãEŽ‘MX“terms“the“digit“ó×2cmmi8¾n“»in“the“name“of“the“ó)#Ñfcmti8ÔoptŽ‘=Ž»command“spšÎfor–ÿ}'c“eŽ‘— ²,‘D>and/or“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘-n ²commands“isŽ¡‘O3Ùreplaced–UUbš¸ãy“a“single“command“(the“maxim˜um“of“the“giv˜en“ones).ŽŸ †‘Bl»2.ŽŽŽ‘O3ÙThe‘r¥Îc–ÿ}'anc“elŽ‘þÖ²command–r¥cancels“an¸ãy“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘3y'²,‘ŸûÎoptŽ‘.²,‘ŸûÎfor–ÿ}'c“eŽ‘el²or“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘**g²commandŽ¡‘O3Ùthat– immediatly“precede“or“folloš¸ãw“it“and“also“cancels“an˜y“Îb‘ÿ}'ackupŽ‘%ŠX²commandŽ¡‘O3Ùthat–UUfollo¸ãws“it.Ž© …‘E3×So–¹ùit“seems“that“the“Îc–ÿ}'anc“elŽ‘"~²command“is“a“command“that“mixes“ev¸ãerything“upŽ¡‘63×again–_after“wš¸ãe“ha˜v˜e“put“ev˜erything“in˜to“a“neat“and“tidy“form!‘žBut“this“only“seemsŽ¡‘63×so.‘äòThe–{¹inš¸ãterpretation“done“b˜y“the“prett˜yprin˜ter“according“to“the“t˜w˜o“rules“statedŽ¡‘63×abšGo•¸ãv“e,‘õcw“as‘Õain“tro˜duced–Õato“b˜e“more“generous“and“more“ exible“with“the“placemen¸ãtŽ¡‘63×of–.®format“primitivš¸ães“in˜to“the“source“coGde.‘dåBecause,›6iafter“all,˜the“format“commandsŽ¡‘63×will–6"not“bGe“inserted“bš¸ãy“hand“(as“the“reader“migh˜t“think“after“viewing“the“examplesŽ¡‘63×giv•¸ãen›¸XabGo“v“e),‘×¾but˜they˜will˜bGe˜inserted˜automatically˜b“y˜the˜prett“yprin“ter˜accordingŽ¡‘63×to–UUthe“prett•¸ãyprin“ting–UUgrammar“that“wš¸ãe“ha˜v˜e“bGeen“in˜trošGduced“to“ab˜o•¸ãv“e.ŽŸb_‘63ׯSummary–ÕTof“F‘ÿ «ormat“CommandsŽŸòC‘63ײT‘ÿ*ªable–ùÒ2.1“shoš¸ãws“a“complete“list“of“all“the“format“command“primitiv˜es“in˜troGducedŽ¡‘63×in–ÂÀthis“part“of“the“b•Go“ok.‘ºThe–ÂÀonly“command“that“wš¸ãasn't“men˜tioned“up“to“no˜w“isŽ¡‘63×the‘$Înul‘‚ØlŽ‘í²primitivš¸ãe–$that“serv˜es“as“a“neutral“(or“empt˜y)“command.‘ÞNo˜w,‘WÅwith“theŽ¡‘63×knoš¸ãwledge–ûØof“all“the“in˜trinsic“and“extrinsiv“features“of“the“prett˜yprin˜ting“methoGdŽ¡‘63×of–¼VPretzel“prett•¸ãyprin“ters,›y“ou–¼Vare“ready“to“read,˜write“or“moGdify“prett•¸ãyprin“tingŽ¡‘63×grammars–·íat“yš¸ãour“will.‘™No˜w,‘Гy˜ou“ha˜v˜e“total“con˜trol“o˜v˜er“the“prett˜yprin˜ting“st˜yle;Ž¡‘63×fully–UUuser“conš¸ãtrolled“prett˜yprin˜ting“is“in“y˜our“grasp.ŽŸ"uí‘63×Ì2.3Ž‘[:W‘þ¦friting›ffPrett•ŒÌyprin“ting˜GrammarsŽŸd ‘O3Ù²\Kno¸ãwing–t‘ÈCWEB‘t‰²and“its“sources,‘|`it“is“clear“to“me“that“doing“a“go•Go“d‘t‘jobŽ¡‘O3Ù(or–UUevš¸ãen“a“fairly“go•Go“d–UUjob)“abGout“prett˜yprin˜ting“is“not“a“simple“task."ŽŸ†C‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[64Ž‘ ]ަ‘63×Y‘ÿ*ªes,›this–ïßis“true.‘AdIn“terms“of“Pretzel,˜\doing“a“go•Go“d–ïßjob“abGout“prett•¸ãyprin“ting"‘ïßisŽ¡‘63×writing–Ùya“go•Go“d›Ùyprett•¸ãyprin“ting˜grammar.‘þ4F‘ÿ*ªor˜simple˜languages˜y“ou˜migh“t˜spGend˜aŽ¡‘63×daš¸ãy–Inor“t˜w˜o“preparing“a“go•Go“d–Ingrammar,‘KÏbut“for“more“complex“languages“(and“moreŽ¡‘63×complex–ˆÎwishes“to“the“loGok“of“the“output)“yš¸ãou“migh˜t“spGend“w˜eeks“and“still“not“bGeŽ¡‘63×happ¸ãy‘ÿ*ª.ŽŽŽŒ‹ç ½\È ýN£8‘'¿¬Ã2.3.‘ÇWRITING–UUPRETTYPRINTING“GRAMMARS‘vó²17ŽŽ ˜G þc㎠ÿ~œrŸŸæd‘FôÎnul‘‚ØlŽŽ’ª¹²empt¸ãy‘UUcommandŽŽŽŽ¤ ‘FôÎindentŽŽ’ª¹²inden¸ãts–UUthe“next“line“a“little“moreŽŽŽŽ¡‘FôÎoutdentŽŽ’ª¹²tak•¸ães›UUbac“k˜the˜last˜inden“tation˜(de-inden“t)ŽŽŽŽ¡‘FôÎfor–ÿ}'c“eŽŽ’ª¹²forces–UUa“line“breakŽŽŽŽ¡‘FôÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽŽ’ª¹²denotes–UUa“pGossible“space“for“a“line“breakŽŽŽŽ¡‘FôÎopt‘ª¨µnŽ‘\*º²,‘UUµn–Ǹ2“f²0µ;–ª¨:“:“:Ž‘ÿ÷;‘ª¨²9¸gŽ’ª¹²denotes–‹an“optional“line“break“with“the“con-Ž¡’ª¹tinš¸ãuation–{line“inden˜ted“a“litte“with“respGect“toŽ¡’ª¹the–¯.normal“starting“pGosition.‘SThis“line“breakŽ¡’ª¹will–UUscore“a“pGenalt¸ãy“of“10µn².ŽŽŽŽŸ0‘FôÎb‘ÿ}'ackupŽŽ’ª¹²denotes–UUa“small“bac¸ãkspaceŽŽŽŽ¡‘FôÎbig‘‰ffŽ‘®for–ÿ}'c“eŽŽ’ª¹²forces–žLa“line“break“and“inserts“a“little“extraŽ¡’ª¹spaceŽŽŽŽŸ‘FôÎno‘‰ffŽ‘®indentŽŽ’ª¹²causes–UUthe“curren¸ãt“line“to“bGe“output“ ushleftŽŽŽŽ¡‘FôÎc–ÿ}'anc“elŽŽ’ª¹²obliterates–Uan¸ãy“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘8[²,‘TûÎoptŽ‘Ó.²,‘TûÎfor–ÿ}'c“eŽ‘$üÕ²orŽ¡’ª¹Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ’ÓÙì²command–ÛPthat“immediatly“precedesŽ¡’ª¹or–çfolloš¸ãws“it“and“also“cancels“an˜y“Îb‘ÿ}'ackupŽ‘# ²com-Ž¡’ª¹mand–UUthat“follo¸ãws“it.ŽŽŽŽŽŽŽŸqÇ‘v£Figure–UU2.1:‘qÇList“of“format“command“primitiv¸ãesŽŽŽŸ¼™‘'¿¬Í2.3.1Ž‘Pÿ¬Mo`difying–€an“existing“grammarŽ©uT‘'¿¬²If–ã_yš¸ãou're“luc˜ky‘ÿ*ª,‘ásomeb•Go“dy–ã_else“had“done“the“w˜ork“already“for“y˜ou.‘äIn“suc˜h“cases,ޤ ‘'¿¬simply–Äêgrab“a“copš¸ãy“of“the“t˜w˜o“Pretzel“input“ les,‘ Îrun“Èpretzel-it“²and“o “y˜ouŽ¡‘'¿¬go.‘NThe–„×Pretzel“homepage“[14Ž‘ ]“should“bšGe“a“go˜o˜d“starting“p˜oin¸ãt“for“the“quest“for“aŽ¡‘'¿¬prett•¸ãyprin“ting–UUgrammar“for“y¸ãour“language.Ž¡‘6¿¬But–what“if“this“grammar“doGesn't“suit“yš¸ãour“preferences?‘UßWhat“if“it“prett˜yprin˜tsŽ¡‘'¿¬ugly–~ÜcoGde?‘î[W‘ÿ*ªell,‘‰=then“yš¸ãou“ha˜v˜e“to“plunge“in˜to“the“ les“and“moGdify“them.‘î[MakingŽ¡‘'¿¬small–2ècš¸ãhanges“that“will“w˜ork“is“quite“easy–ÿ*ª.‘fMF“or–2èexample,‘9Êif“y˜ou“only“dislik˜e“the“w˜a˜yŽ¡‘'¿¬certain–>àsymš¸ãbGols“come“out“of“the“prett˜yprin˜ter,‘C]loGok“in“the“formatted“tok˜en“ le“andŽ¡‘'¿¬try–Í’to“ gure“out,‘ë¡where“yš¸ãou“can“c˜hange“it.‘Ú}Or“if“y˜ou“dislik˜e“forced“line“breaks“atŽ¡‘'¿¬certain–Üplaces,‘ý¬just“go“inš¸ãto“the“grammar“and“remo˜v˜e“the“Îfor–ÿ}'c“eŽ‘ βfrom“the“attributeŽ¡‘'¿¬de nition.Ž¡‘6¿¬If–k”yš¸ãour“wishes“co˜v˜er“more“ma‘Ž8jor“aspGects“of“the“la˜y˜out,‘q$then“y˜ou“should“mak˜e“aŽ¡‘'¿¬copš¸ãy––mof“the“ le“and“rename“it“to“something“that“re ects“the“c˜hange.‘2%Also,‘¼œy˜ou“migh˜tŽ¡‘'¿¬put–¤³a“new“commen¸ãt“at“the“bšGeginning“of“the“ le“that“describ˜es“who“y¸ãou“are“and“whatŽ¡‘'¿¬this–Çénew“grammar“doGes“di erenš¸ãtly“than“the“grammar“y˜ou“started“from.‘ɃNo˜w“y˜ouŽ¡‘'¿¬can–hAstart“to“expšGerimen¸ãt.‘ª‹The“go˜o˜d“thing“ab˜out“this“is“that“yš¸ãou“can“alw˜a˜ys“fallŽ¡‘'¿¬bacš¸ãk–(xto“the“original“cop˜y“and“start“from“there“again.‘bÓIf“y˜ou“get“y˜our“new“grammarŽ¡‘'¿¬w•¸ãorking,‘æ›con“tact–Éthe“Pretzel“home“page“[14Ž‘ ]“so“it“can“bGe“added“to“the“list“of“ lesŽ¡‘'¿¬for–l\certain“languages.‘¶ÝOther“pGeople“can“then“use“yš¸ãour“grammar“and“don't“ha˜v˜e“toŽ¡‘'¿¬go–UUthrough“the“same“w¸ãork“again.Ž¡‘6¿¬F‘ÿ*ªor–#[similar“languages“(likš¸ãe“Ja˜v‘ÿqÇa“and“ÇC²)‘#&y˜ou“could“try“to“tak˜e“a“grammar“forŽ¡‘'¿¬the–[u rst“one“and“try“to“moGdify“it“that“it“ ts“the“second“one.‘„&In“an¸ãy“case,‘\üstudyingŽ¡‘'¿¬existing–UUgrammars“is“alw•¸ãa“ys›UUv“ery˜helpful˜if˜y“ou˜don't˜ha“v“e˜m“uc“h˜expGerience.ŽŸ¸˜‘'¿¬Í2.3.2Ž‘Pÿ¬W‘þàriting–€a“new“Grammar“from“Scratc hަ‘'¿¬²If–çyš¸ãou're“unluc˜ky‘ÿ*ª,‘ý%and“y˜ou“can't“ nd“a“suitable“grammar“then“y˜ou“will“ha˜v˜e“to“startŽ¡‘'¿¬from–­scratcš¸ãh.‘[If“y˜ou're“in“this“situation,‘ there“are“t˜w˜o“pGossible“w˜a˜ys“of“con˜tin˜uing:ŽŸ¼™‘3ø1.ŽŽŽ‘@¿®Most–“æprogramming“languages“are“con¸ãtext“free“and“so“there“should“bGe“a“con-Ž¡‘@¿®text–µfree“grammar“for“yš¸ãour“language“a˜v‘ÿqÇailable“either“in“the“reference“w˜orksŽ¡‘@¿®(i.e.–¸Nthe“b•Go“oks)–¸Nthat“\de ne"“the“language,‘ or“somewhere“in“the“in¸ãternet,ŽŽŽŒ‹øD ½\È ýN£8‘63ײ18’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜G ý„‘O3Ù²where–$Dthere“could“bGe“compilers“for“yš¸ãour“language“a˜v‘ÿqÇailable“in“the“source,‘.andޤ ‘O3Ùif–}‹so,‘ǘa“con¸ãtext“free“grammar“for“the“parser“of“that“compiler“is“almost“al-Ž¡‘O3Ùw•¸ãa“ys–ܽincluded“there.‘þY‘ÿ*ªou“could“start“with“suc¸ãh“a“grammar“and“simply“addŽ¡‘O3Ùformatting–UUinstructions“to“the“rules“as“y¸ãou“wish.ŽŸM´‘Bl»2.ŽŽŽ‘O3ÙY‘ÿ*ªou–jcould“start“enš¸ãtirely“from“scratc˜h,‘oßloGok“at“the“language“and“start“writingŽ¡‘O3Ùa›„prett•¸ãyprin“ting˜grammar˜that˜w“orks˜with˜the˜coGde˜y“ou˜are˜w“orking˜on.‘X,ThisŽ¡‘O3Ùmighš¸ãt–^™seem“more“w˜ork“than“the“ rst“alternativ˜e,‘òbut“sometimes“is“still“feasible.ŽŸ›h‘E3×T‘ÿ*ªo–jgo“with“the“ rst“alternativ•¸ãe,‘¯Dy“ou–jwill“ha•¸ãv“e–jto“ha•¸ãv“e–ja“full“blo¸ãwn“languageŽ¡‘63×grammar–y*a¸ãv‘ÿqÇailable.‘ÝGBut“these“grammars“(as“for“example“with“ÇC‘y!²or“ÇCŸÿ²++Ž‘Ž<)“tend“toŽ¡‘63×bGe–Iðrather“large“and“ugly‘ÿ*ª,›‡resulting“in“prett•¸ãyprin“ting–Iðgrammars,˜that“are“dicultŽ¡‘63×to–q‡understand“and“dicult“to“moGdify‘ÿ*ª.‘Æ^Ho•¸ãw“ev“er,‘x”a›q‡prett“yprin“ting˜grammar˜doGesn'tŽ¡‘63×ha•¸ãv“e–G;to“bGe“a“full“bloš¸ãwn“language“grammar“after“all.‘mThe“fact“that“suc˜h“a“grammarŽ¡‘63×will–\·solemnly“bšGe“used“to“create“a“\prett•¸ãyprin“ted"–\·translation“of“a“bit“of“source“co˜de“itŽ¡‘63×doGesn't–X†necesserily“ha•¸ãv“e–X†to“ha•¸ãv“e›X†an“y˜resem“blence˜to˜a˜language˜grammar.‘ƒIn˜ÇP‘ÿ ascalŽ¡‘63ײfor–)&instance,‘^ÆforŽ‘^²-,‘^ÆwhileŽ‘¸¼²-“and“ÆelseŽ‘nвless“ÆifŽ‘ Þy²-statemen¸ãts“are“normally“formatted“in“aŽ¡‘63×vš¸ãery–Õ¸similar“w˜a˜y;‘Bso“the“grammar“m˜ustn't“distinguish“bGet˜w˜een“the“three“constructs.Ž¡‘63×This–Îresults“in“prett•¸ãyprin“ting–Îgrammars“that“can“bGe“quite“di eren¸ãt“from“the“normalŽ¡‘63×grammars–UUof“the“programming“languages.‘qÇIn“most“cases“they“are“m•¸ãuc“h‘UUsmaller.Ž¡‘E3×Ho•¸ãw“ev“er,‘½ if›¨Ky“ou˜start˜from˜scratc“h˜and˜don't˜w“an“t˜to˜use˜an˜existing˜referenceŽ¡‘63×grammar,‘šryš¸ãou–Œ could“still“consult“it“once“and“again“if“y˜ou“are“stuc˜k“with“y˜our“o˜wnŽ¡‘63×one.‘áÌLikš¸ãe–Ðthe“language“grammar,‘.¬the“prett˜yprin˜ting“grammar“m˜ust“bGe“able“toŽ¡‘63×parse–Œ‡Îevery“²construct“that“will“appGear“in“the“input.‘\But“it's“no“problem“if“theŽ¡‘63×prett•¸ãyprin“ting–lUgrammar“mighš¸ãt“sw˜allo˜w“coGde“that“isn't“syn˜tactically“correct.‘¶ÆW‘ÿ*ªe'reŽ¡‘63×talking›ÔŽPrett•¸ãyprin“ters˜here˜and˜not˜Compilers.‘ïqSections˜2.3.3˜and˜2.3.5˜will˜elab-Ž¡‘63×orate–ïŸmore“on“the“issue“of“\grammar“correctness."‘@¦In“anš¸ãy“case,‘2ha˜ving“a“loGok“atŽ¡‘63×a•¸ãv‘ÿqÇailable›UUprett“yprin“ting˜grammars˜in˜adv‘ÿqÇance˜helps˜a˜lot.ŽŸ±r‘63×Í2.3.3Ž‘_s×Conš text–€F‘þàree“v˜ersus“Con˜text“Sensitiv˜eŽŸuT‘63ײLošGoking–®at“the“history“of“the“prett•¸ãyprin“ting–®metho˜d“that“Pretzel“emploš¸ãys“(see“c˜hap-Ž¡‘63×ter–w¡5),‘£ùwš¸ãe“can“see“that“the“grammars“that“the“ rst“systems“started“with“w˜ere“con˜textŽ¡‘63×sensitivš¸ãe.‘,‘This–èîmeans“that“there“actually“are“ready“to“use“con˜text“sensitiv˜e“pret-Ž¡‘63×t•¸ãyprin“ting–.šgrammars“around“for“manš¸ãy“languages“suc˜h“as“ÇP‘ÿ ascal“²[29Ž‘ ]“and“ÇC²/ÇCŸÿ²++ŽŽ¡‘63×[33Ž‘ ].‘pThere–POis“evš¸ãen“a“system“similar“to“Pretzel“but“with“a“more“complete“approac˜hŽ¡‘63×called–]¯ÇSPIDER‘]­²[49Ž‘ ]“that“amoung“other“things“created“a“prett•¸ãyprin“ter–]¯from“a“con-Ž¡‘63×text–UUsensitivš¸ãe“prett˜yprin˜ting“grammar.Ž¡‘E3×So–4whš¸ãy“doGes“Pretzel“use“con˜text“free“grammars“an˜yw˜a˜y?‘The“answ˜er“to“thisŽ¡‘63×problem–}Álies“in“the“toGols“that“Pretzel“relies“on.‘ë The“prett•¸ãyprin“ters–}Áthat“PretzelŽ¡‘63×generates–â”are“actually“parsers,‘ù‡and“instead“of“writing“a“whole“new“parser“generator,Ž¡‘63×Pretzel–Ù©relies“on“the“wš¸ãell“kno˜wn“ÇUNIX‘ÙŠ²tošGol“Bison,‘òethat“do˜es“just“the“wš¸ãork“w˜e“need.Ž¡‘63×But,–UUin“e ect,“Bison“input“is“con¸ãtext“free!‘qÇHmmm.Ž¡‘E3×No•¸ãw›u­con“text˜free˜grammars˜are˜a˜little˜more˜restrictiv“e˜than˜con“text˜free˜ones,Ž¡‘63×and–1so“it“is“not“pGossible“to“transform“anš¸ãy“con˜text“sensitiv˜e“grammar“of“y˜our“c˜hoiceŽ¡‘63×inš¸ãto–Ca“con˜text“free“one.‘k±This“is“unfortunate,‘Fºbut“this“is“a“fact“w˜e“ha˜v˜e“to“liv˜e“with.Ž¡‘63×My–Äknoš¸ãwledge“of“formal“language“theory“is“not“v˜ery“deep,‘·Hbut“I‘’suspGect“that“parsingŽ¡‘63×with–ãÙconš¸ãtext“sensitiv˜e“grammars“is“not“trivial“and“that“this“is“the“reason“wh˜y“noŽ¡‘63×generators–UUlikš¸ãe“Bison“exist“in“a“con˜text“sensitiv˜e“ a˜v˜our.Ž¡‘E3×So–°0conš¸ãtext“free“is“what“w˜e“ha˜v˜e“to“liv˜e“with.‘:»F‘ÿ*ªrom“studying“existing“prett˜yprin˜t-Ž¡‘63×ing–ÃWsystems“(again“see“cš¸ãhapter“5“for“details)“it“seems“that“con˜text“sensitiv˜e“is“theŽ¡‘63×w•¸ãa“y–mFto“go“in“prett•¸ãyprin“ting,‘sBand–mFthis“seems“bad“for“Pretzel.Ÿü^ÿ±6ŽŽ‘ 6 ²But“Pretzel“is“a“pro-Ž‘63ן¥á‰ff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»I‘ZÈactually–ZëÔis“»a“quite“sevšÃŽere“restriction“and“will“probably“bw“an“ted˜and˜y“ou˜don't˜kno“w˜wh“y‘ÿ*ª.‘FThe˜insigh“t˜that˜follo“ws˜from˜this˜situationŽ¡‘63×is–Tvš¸ãery“frustrating:‘oPnothing“comes“for“free!‘nSearc˜hing“for“bugs“in“prett˜yprin˜tingŽ¡‘63×grammars–UUis“as“necessary“as“in“normal“programs.ŽŸÜ ‘63ׯThe–ÕTÈerror“ÆT‘ÿ «ok®9enŽŸuT‘63ײIf–Ösa“Pretzel“prett•¸ãyprin“ter–Öscan't“handle“a“sequence“of“input“coGde,‘6ºit“will“outputŽ¡‘63×Înothing²,‘š•not–Yˆevš¸ãen“an“error“message.‘~aBut“there“is“still“a“w˜a˜y“to“notice“this“fact.Ž¡‘63×There–ȵis“a“spGecial“Èerror“²tokš¸ãen“that“ma˜y“bGe“used“in“suc˜h“circumstances.‘ËæY‘ÿ*ªou“canŽ¡‘63×place–it“inš¸ãto“y˜our“grammar“at“an˜y“place,‘and“it“will“matc˜h“a“sequence“of“tok˜ens“notŽ¡‘63×co•¸ãv“ered›UUb“y˜the˜other˜rules˜in˜question.Ž¡‘E3×A‘3rhandy–3zplace“to“put“an“Èerror“²tokš¸ãen“is“righ˜t“at“the“bGeginning“of“the“grammar.Ž¡‘63×Saš¸ãy‘ÿ*ª,‘Óa–ì Èfinal“²tok˜en“is“the“tok˜en“that“ev˜erything“reduces“to“in“y˜our“grammar.‘6)T‘ÿ*ªoŽ¡‘63×notice–UUa“parse“error,“y¸ãou“can“for“example“writeŽ©a>‘63×Èfinal‘¿÷:‘?ýexpŽ¡‘`3¿|‘?ýstmtŽ¡‘@³Ñ//–?ýcheck“for“parse“errors:Ž¡‘`3¿|–?ýerror‘ ú{“"syntax“error"“}Ž¡‘63×;ަ‘63ײand–Y;so“the“text“\synš¸ãtax“error"“appGears“in“the“output“ev˜erywhere“Pretzel“w˜asn'tŽ¡‘63×able–UUto“parse“the“input.Ž¡‘E3×Y‘ÿ*ªou–È%maš¸ãy“place“the“Èerror“²tok˜en“in“an˜y“place“y˜ou“lik˜e,‘äbas“long“as“it“is“on“the“righ˜tŽ¡‘63×hand–7‰side“of“the“colon.‘gØUsing“the“Èerror“²tokš¸ãen“in“other“places“than“at“the“end,‘=~y˜ouŽ¡‘63×ma¸ãy–iproGduce“grammars“that“are“more“robust“and“can“handle“unforseen“constructsŽ¡‘63×more‘UU exibly‘ÿ*ª.ŽŸÜ ‘63ׯW‘ÿ «atcš®9hing–ÕTthe“P˜arseŽŸuT‘63ײThe–Èpretzel-it“²program“o ers“a“È-d“²option“that“proGduces“a“prett•¸ãyprin“ter‘whic“hŽ¡‘63×is–|Hin“\debugging“moGde"“bš¸ãy“default.‘æ This“means“that“during“prett˜yprin˜ting,‘ÆtheŽ¡‘63×program–ù:will“output“a“lot“of“debugging“information“to“the“standard“error“streamŽ¡‘63×(usually–Ñthe“screen).‘äñThis“information“displaš¸ãys“what“kind“of“tok˜en“has“bGeen“readŽ¡‘63×from–ù.the“input“(and“hoš¸ãw“it“loGoks)“and“what“rule“of“the“prett˜yprin˜ting“grammar“hasŽ¡‘63×bšGeen–¤÷c¸ãhosen.‘`®Additionally‘ÿ*ª,‘¸àthe“È-d“²option“pro˜duces“a“ le“that“con¸ãtains“an“analysisŽ¡‘63×of–n yš¸ãour“prett˜yprin˜ting“grammar.‘½©If“y˜our“input“name“is,–tósa˜y‘ÿ*ª,“Èfoo²,“then–n this“ le“willŽ¡‘63×bGe–UUcalled“Èfoo.output².Ž¡‘E3×Here's–8ãan“example“of“the“debugging“output“(tak¸ãen“from“a“run“on“the“Èsmall-example.simpasŽ¡‘63ײexample):ަ‘63×ÈStarting‘?ýparseŽ¡‘63×Entering–?ýstate“0Ž¡‘63×Reading–?ýa“token:“Next“token“is“260“(IFif)Ž¡‘63×Shifting–?ýtoken“260“(IF),“Entering“state“1Ž¡‘63×Reading–?ýa“token:“Next“token“is“266“(IDa)Ž¡‘63×Shifting–?ýtoken“266“(ID),“Entering“state“4Ž¡‘63×Reducing–?ývia“rule“7“(line“195),“ID‘ ú->“expŽ¡‘63×state–?ýstack“now“0“1Ž¡‘63×Entering–?ýstate“8Ž¡‘63×Reading–?ýa“token:“Next“token“is“259“(BINOP=)Ž¡‘63×Shifting–?ýtoken“259“(BINOP),“Entering“state“11ŽŽŽŒ‹-r ½\È ýN£8‘'¿¬Ã2.3.‘ÇWRITING–UUPRETTYPRINTING“GRAMMARS‘vó²21ŽŽ ˜G ý„‘'¿¬ÈReading–?ýa“token:“Next“token“is“265“(NUM1)ޤ ‘'¿¬Shifting–?ýtoken“265“(NUM),“Entering“state“3Ž¡‘'¿¬Reducing–?ývia“rule“8“(line“196),“NUM‘ ú->“expŽ¡‘'¿¬state–?ýstack“now“0“1“8“11Ž¡‘'¿¬Entering–?ýstate“15Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“261“(THENthen)Ž¡‘'¿¬Reducing–?ývia“rule“9“(line“197),“exp“BINOP“exp‘ ú->“expŽ¡‘'¿¬[...]Ž¡‘'¿¬Entering–?ýstate“14Ž¡‘'¿¬Reducing–?ývia“rule“2“(line“102),“stmt_list“SEMI“stmt‘ ú->“stmt_listŽ¡‘'¿¬state–?ýstack“now“0Ž¡‘'¿¬Entering–?ýstate“5Ž¡‘'¿¬Now–?ýat“end“of“input.Ž¡‘'¿¬Shifting–?ýtoken“0“($),“Entering“state“19Ž¡‘'¿¬Now–?ýat“end“of“input.Ž©‘'¿¬²Evš¸ãery–fÅtime,‘–|the“scanner“reads“a“tok˜en,‘–|the“tok˜en“coGde“(lik˜e“ÈIF›f‰²or“ÈID²)˜is“prinš¸ãted“whic˜hŽ¡‘'¿¬is›é…follo•¸ãw“ed˜b“y˜the˜actual˜con“ten“ts˜of˜the˜tok“en˜(lik“e˜\Èa²"˜in˜case˜of˜the˜iden“ti er).Ž¡‘'¿¬Evš¸ãery–tçtime“the“parser“reduces“a“tok˜en,‘|Ëit“prin˜ts“the“rule“that“it“uses.‘Ð|The“n˜um˜bGerŽ¡‘'¿¬of–—€the“rules“and“also“the“state“information“will“bšGecome“clear“if“y¸ãou“lo˜ok“at“theŽ¡‘'¿¬Èsimpas.output–² le“and“learn“abGout“the“inš¸ãternals“of“the“Pretzel“parsing“mec˜hanismŽ¡‘'¿¬(bš¸ãy–UUloGoking“at“the“man˜ual“page“Èbison(1)²).ŽŸþ6‘'¿¬ÆCon®9text–ÕTF‘ÿ «ree“againŽŸuT‘'¿¬²As–ÛÒdescribšGed“ab˜o•¸ãv“e,‘ýqcon“text–ÛÒfree“grammars“are“prettš¸ãy“restrictiv˜e,‘ýqsometimes“ev˜enŽ¡‘'¿¬more–UUrestrictivš¸ãe“than“w˜e“lik˜e.‘qÇNote“that“rules“lik˜eަ‘'¿¬Èdecl_head–?ýid“:‘¿÷int_like“idŽ¡‘'¿¬;ަ‘'¿¬²to–bsturn“an“Èint‘¡E‰ff&fŽ‘Ç«like“²tokš¸ãen“in˜to“the“head“of“a“declaration“if“it“is“follo˜w˜ed“b˜y“anŽ¡‘'¿¬idenš¸ãti er–UUare“con˜text“senstiv˜e“and“therefore“forbidden.Ž¡‘6¿¬See–3Ÿalso“the“next“cš¸ãhapter,‘:]espGecially“section“3.1.4“for“a“few“more“tips“and“tric˜ksŽ¡‘'¿¬for–UUwriting“and“debugging“prett•¸ãyprin“ting‘UUgrammars.ŽŸþ6‘'¿¬Í2.3.6Ž‘Pÿ¬Exp`eriencesŽŸuT‘@¿®²\With–fÈCWEB²,“there'll“alw•¸ãa“ys–fbGe“something“someone“w•¸ãan“ts–fand“can't“ha•¸ãv“e,Ž¡‘@¿®bšGecause–Åit“tries“to“do“to˜o“m•¸ãuc“h–Åin“its“kš¸ãernel.‘ÀÔWitness“the“recen˜t“com-Ž¡‘@¿®plainš¸ãt–6in“this“newsgroup“from“someone“trying“to“put“mak˜e les“in“theŽ¡‘@¿®ÈCWEB–g³²sources.‘¨îÈCWEAVE“²tries–g·to“bšGe“the“p˜erfect“ÇC‘g³²programming“to˜ol“righ¸ãtŽ¡‘@¿®out–À:of“the“bGoš¸ãx,‘Þ and“so“comes“up“completely“unable“to“handle“mak˜e les."ŽŸ‘@¿®Barry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŸ‘'¿¬Remem¸ãb•Ger,‘ï”writing›лgo“o“d˜prett•¸ãyprin“ting˜grammars˜is˜dicult.‘ãùSo˜don't˜o“v“erdo˜it.Ž¡‘'¿¬It's–×Iprett¸ãy“dicult“(if“not“impGossible)“to“come“out“with“a“\complete"“grammar“thatŽ¡‘'¿¬will–Ñ—handle“all“cases“brillianš¸ãtly‘ÿ*ª.‘æŒSo“if“y˜ou're“happ˜y“with“the“w˜a˜y“y˜our“cošGde“lo˜oks,Ž¡‘'¿¬that's– ne.‘«If“something“turns“out“wrongly‘ÿ*ª,›Bask“y¸ãourself,˜what“actually“Îis“²wrongŽ¡‘'¿¬here?ŽŽŽŒ‹: ½\È ýN£8‘63ײ22’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜GŽŒ‹F\ ½\È ýN£8 ˜G ýÏ‘'¿¬ÊChapter‘Ç 3ŽŸ2‘'¿¬ÅPretzel‘ T{Hac‘ÿ8õkingŽŸ4‘'¿¬²In–ÆÃthis“cš¸ãhapter“w˜e'll“ha˜v˜e“a“loGok“in˜to“the“guts“of“Pretzel.‘BAW‘ÿ*ªe'll“see“ho˜w“the“in˜ternalsޤ ‘'¿¬of–b Èpretzel-it“²wš¸ãork“and“what“other“nice“things“y˜ou“can“do“with“the“system.‘—èThisŽ¡‘'¿¬cš¸ãhapter–ÿis“aimed“at“programmers“who“w˜an˜t“to“proGduce“simple,‘«ecien˜t“and“elegan˜tŽ¡‘'¿¬prett•¸ãyprin“ters–for“their“language.‘HÝHo•¸ãw“ev“er,‘®óI‘œõrecommend–reading“at“least“the“ rstŽ¡‘'¿¬subsection–UUabšGout“adding“ÇC“²co˜de“to“the“rules,“evš¸ãen“when“y˜ou“dislik˜e“hac˜king.ŽŸ ø½‘'¿¬Ì3.1Ž‘L¦Adding–ffó*Œ-øff cmcsc10ÕC“ÌCos3de“to“the“RulesŽŸç‘'¿¬²Y‘ÿ*ªes,‘›éyš¸ãou–mŽcann“add“y˜our“o˜wn“ÇC‘mS²coGde“to“the“attribute“de nition“parts“of“the“formattedŽ¡‘'¿¬grammar–õ%and“formatted“tokš¸ãen“ les.‘ Q8A‘ôºt˜ypical“application“of“this“feature“is“toŽ¡‘'¿¬dynamically–"…tš¸ãypGeset“constructed“t˜ypGe“names“(as“Æt®9ypQÇedefŽ‘(‚y²s“in“ÇC‘"x²or“ÆclassŽ‘L²es“in“Ja˜v‘ÿqÇa)Ž¡‘'¿¬correctly‘ÿ*ª.Ž¡‘6¿¬The–hÓproblem“with“Pretzel“is,‘­³that“wš¸ãe“w˜ould“lik˜e“to“pGerform“di eren˜t“actionsŽ¡‘'¿¬depGending–Üon“the“conš¸ãtext“of“the“tok˜en“that“the“prett˜yprin˜ter“ nds.‘UôF‘ÿ*ªor“example,‘ŽinŽ¡‘'¿¬ÇC‘Oвnormal–O‹idenš¸ãti ers“should“bGe“t˜ypGeset“in“italics,‘P´but“iden˜ti ers“that“are“the“namesŽ¡‘'¿¬of‘cÆt®9ypQÇedefŽ‘(à ²s–cshould“bšGe“t¸ãyp˜eset“in“b˜old.‘› Pretzel“can't“handle“this“situation“withoutŽ¡‘'¿¬tricš¸ãky–þËmanipulations“of“the“attribute“de nitions,‘bGecause“the“t˜ypGe“of“grammar“thatŽ¡‘'¿¬Pretzel–§(uses“is“essenš¸ãtially“con˜text“free“(see“section“2.3.3“for“a“discussion“of“relatedŽ¡‘'¿¬problems).ŽŸå/‘'¿¬Í3.1.1Ž‘Pÿ¬Example–€for“T‘þàok ensŽŸuT‘'¿¬²Hoš¸ãw–rŒhandle“this“situation?‘ÉkPretzel“allo˜ws“y˜ou“to“add“ÇC‘rB²coGde“to“y˜our“attributeŽ¡‘'¿¬de nitions.‘tHere–89is“a“small“example,‘pòhoš¸ãw“this“could“bGe“used“in“formatted“tok˜enŽ¡‘'¿¬ les:ޤn®‘'¿¬È[a-zA-Z][a-zA-Z0-9_]*‘ÿôID› ú{–?ý"{\\it“"˜[escaped_underlines(yytext)]“"}"“}Ž¡‘6¿¬²The–±purpGose“of“this“line“is“to“scan“tokš¸ãens“that“are“iden˜ti er“names“and“returnޤ ‘'¿¬\ÈID²"‘Ô®t•¸ãypGe›ÔÏtok“ens˜to˜the˜prett“yprin“ting˜parser,‘ô­but˜also˜to˜mo•Gdify˜the˜app“earanceŽ¡‘'¿¬of–üEthe“matc¸ãhed“text“bšGefore“returning.‘f–In“this“example“there“is“ÇC‘ü²co˜de“inside“theŽ¡‘'¿¬attribute–›7de nition.‘CmThis“coGde“is“encircled“in“angled“brac•¸ãk“ets–›7\È[²"“and“\È]²"“andŽ¡‘'¿¬can–jybGe“anš¸ãy“sequence“of“ÇC‘j2²statemen˜ts“with“one“cen˜tral“propGert˜y:‘œThe“coGde“partŽ¡‘'¿¬mš¸ãust–X†reduce“to“the“ÆA®9ttributeŽ‘3̸“²class,‘YRi.e.“the“return“t˜ypGe“m˜ust“me“a“pGoin˜ter“to“anŽ¡‘'¿¬ÆA®9ttributeŽ‘ZŠÅ²ob‘Ž8ject.‘WGThe‘ÓÆA®9ttributeŽ‘5Ðì²class–Óis“a“spšGecial“ÇCŸÿ²++Ž‘”class“that“b˜elongs“to“theŽ¡‘'¿¬Pretzel–UUsystem“and“is“conš¸ãtained“in“the“run˜time“library‘ÿ*ª.Ÿü^ÿ±1ŽŽŽ¡‘6¿¬²T‘ÿ*ªo–8ãthis“e ect,‘qÇthe“Îesc–ÿ}'ap“e“d‘‰ffŽ‘®underlines–8ã²function“called“abGo•¸ãv“e›8ãm“ust˜ha“v“e˜the˜sy“onpsis:Ž‘'¿¬Ÿ ‰ff‰¬Ÿ J=‘ "5Ÿý-:¼1ŽŽŽ‘LÜ»A‘€|description–€¨of“hoÃŽw“to“use“obxäjects“of“this“class“and“related“functions“can“b6²);ŽŸ$‘63×The–İmatc¸ãhed“text“is“accessible“via“a“string“(i.e.“a“Æc®9harŽ‘Fo¸“²v‘ÿqÇariable)“called“ÎyytextŽ‘O¨².‘ATheޤ ‘63×delimiters–»øof“cošGde“are“angled“brac•¸ãk“ets–»øas“explained“ab˜o•¸ãv“e.‘>¨If–»øangled“brac•¸ãk“ets‘»øapp˜earŽ¡‘63×in–Ó„the“ÇC‘Óc²coGde“itself,‘óanš¸ãy“closing“brac˜k˜et“m˜ust“bšGe“escap˜ed“bš¸ãy“a“bac˜kslash“in“orderŽ¡‘63×for–UUPretzel“to“recognize“it“correctly‘ÿ*ª.Ž© ‘E3×T‘ÿ*ªo–?ôhelp“simplify“the“synopsis“of“the“Îesc–ÿ}'ap“e“d‘‰ffŽ‘®underlinesŽ‘Y‰í²function,‘z›wš¸ãe“ma˜y“useŽ¡‘63×spšGecial–Lrfunctions“in“the“run¸ãtime“library“that“b˜elong“to“the“ÆA®9ttributeŽ‘6^*²class.‘nÑTheseŽ¡‘63×are–r,the“t•¸ãw“o–r,functions“Îcr–ÿ}'e“ateŽ›#&²and“ÎjoinŽ‘g².‘ÈKThe“Îcr–ÿ}'e“ateŽ˜²function“tak¸ães“a“string“(i.e“aŽ¡‘63ׯc®9harŽ‘Kµ–¸²)–ÓÀand“turns“it“inš¸ãto“an“attribute.‘í So,‘3[if“y˜ou“ha˜v˜e“written“a“function,‘3[sa˜yŽ¡‘63×Îesc‘‰ffŽ‘®ulŽ‘P u²,›Aéthat–™turns“a“string“in¸ãto“the“same“string“with“escapGed“underlines,˜then“anŽ¡‘63×implemenš¸ãtation–UUof“the“function“abGo˜v˜e“could“loGok“lik˜e“this:ŽŸ$0‘@3ØÆA®9ttributeŽ‘où¸‘UUÎesc–ÿ}'ap“e“d‘‰ffŽ‘®underlinesŽ‘T_Z²(Æc®9harŽ‘¿¸‘UUÎsŽ‘>6²)ަ‘@3ظfަ‘J3ÙÆreturnŽ‘m‡^Îcr–ÿ}'e“ateŽ’‡µ,²(Îesc‘‰ffŽ‘®ulŽ‘ìž²(ÎsŽ‘èá²));ަ‘@3ظgަŸ$‘63ײThe‘agÎjoinŽ‘e ²function–agsimply“joins“t•¸ãw“o–agor“more“(up“to“ten)“attributes“together“in¸ãto“anŽ¡‘63×new‘UUone.ŽŸ.6‘63×Í3.1.2Ž‘_s×Example–€for“GrammarsŽŸ†*‘63ײBut–Ýyš¸ãou“can“do“more“with“this“feature.‘$`Here's“an“example“coGde“fragmen˜t“thatŽ¡‘63×handles–@the“\correct"“formatting“of“Æt®9ypQÇedefŽ‘)b4²s“in“ÇC².“In“ÇC‘²yš¸ãou“can“construct“y˜ourŽ¡‘63×oš¸ãwn–¨Óshorthands“for“t˜ypGes“b˜y“using“the“Æt®9ypQÇedefŽ‘.±š²construct,‘ý²th˜us“making“normalŽ¡‘63×iden•¸ãti ers›óµlik“e˜ÎL‘ÿ}'engthŽ‘%°²to˜t“ypGe˜names.‘LèHere's˜an˜example,‘Mif˜y“ou're˜not˜aquain“tedŽ¡‘63×with‘UUÇC²:ŽŸ$0‘@3ØÆt®9ypQÇedefŽ‘hé!in®9tŽ‘yúãÎL‘ÿ}'engthŽ’—Ã{²;ަ‘@3ØÎL‘ÿ}'engthŽ‘aQÅlŽ‘d膲;ŽŸŸ$‘63×The–Mìidenš¸ãti er“ÎL‘ÿ}'engthŽ‘$dp²has“the“status“of“a“t˜ypšGe“name“and“this“should“b˜e“re ected“inŽ¡‘63×the–UUtš¸ãypGesetting“st˜yle.‘qÇSo“the“w˜a˜y“w˜e“w˜an˜t“it“w˜ould“bGe“lik˜e“this:ŽŸ$0‘@3ØÆt®9ypQÇedefŽ‘hé!in®9tŽ‘yúãLengthŽ’*ײ;ަ‘@3ØÆLengthŽ‘f¹!ÎlŽ‘jOâ²;ŽŸŸ$‘E3×The–jsidea“bšGehind“a“simple“solution“to“this“problem“is“to“use“a“simple“lo˜okupŽ¡‘63×table–‡to“kš¸ãeep“trac˜k“of“all“iden˜ti ers“that“ha˜v˜e“bGeen“Æt®9ypQÇedefŽ‘(}{²ed.‘_-Then,‘(°if“w˜e“ha˜v˜e“toŽ¡‘63×prett•¸ãyprin“t–ó5an“iden•¸ãti er,‘Õw“e–ó5simply“loGok“inš¸ãto“the“table“and“from“the“result“w˜e“kno˜wŽ¡‘63×whether–UUw¸ãe“can“use“bGoldface“or“italics.ަ‘E3×A‘ƒ$prett•¸ãyprin“ter–ƒYfor“ÇCŸü^ÿ±2ŽŽ‘ÿ—²mighš¸ãt“ha˜v˜e“rules“lik˜e“these“to“handle“Æt®9ypQÇedefŽ‘*f¦²statemen˜ts:Ž©$‘63×Ètypedef–?ý:“TYPEDEF_LIKE“INT_LIKE“ID‘î[“install($3);“]Ž¡’3_{–?ý$1“"\\“"“$2“"\\“{\\bf“"“$3“"}"“}Ž¡‘63×;ަ‘63ײ(W‘ÿ*ªe–\£assume“that“Îinstal‘‚ØlŽ‘"—²is“a“function“that“installs“an“iden¸ãti er“in“the“loGokup“tableŽ¡‘63×and–UUthat“Îlo‘ÿ}'okupŽ‘"¤d²is“a“function“that“tells“us“if“an“iden¸ãti er“is“in“the“table.)ŽŸ ‘E3×What–œ§w¸ãe“see“here“is“called“Îstarting‘êc–ÿ}'o“de².‘48Starting–œ§cošGde“is“co˜de“in“angled“brac•¸ãk“etsŽ¡‘63×that–Úsis“placed“bGefore“the“attribute“de nition.‘HÑIt“can“conš¸ãtain“an˜y“sequence“of“ÇC‘ÚT²coGdeŽ‘63ן|]‰ff‰¬Ÿ J=‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»LikÃŽe–ÕXthe“one“in“the“Ïlanguages/cee“»subÿÜ{“[lookup($1)“?“create("{\\bf“")“:Ž¡’¿ÿUcreate("{\\it–?ý")]“$1“"}"“}Ž¡‘'¿¬;ަ‘'¿¬²Note– ¶that“wš¸ãe“are“making“use“of“the“conditional“expression“of“ÇC².“Remem˜bGer“thatŽ¡‘'¿¬the–ÎcošGde“within“the“attribute“de nition“has“to“turn“out“as“t¸ãyp˜e“ÆA®9ttributeŽ‘2Þ¸“²and“soŽ¡‘'¿¬wš¸ãe–´Ãuse“the“Îcr–ÿ}'e“ateŽ‘!—T²function“again“to“turn“a“string“in˜to“an“attribute.‘So“here“againŽ¡‘'¿¬wš¸ãe–¥Ðuse“coGde“Îwithin“²attribute“de nitions“and“all“in“all,‘¹ïw˜e“can“use“iden˜ti ers“as“ÈidŽ¡‘'¿¬²tokš¸ãens–UUin“the“grammar“and“kno˜w“that“they“are“t˜ypGeset“correctly‘ÿ*ª.Ž¡‘6¿¬Apart–~nfrom“cošGde“b˜efore“the“attribute“de nition“and“co˜de“within“attribute“de -Ž¡‘'¿¬nitions,‘ƒ¿there–zwcan“also“bšGe“co˜de“after“the“attribute“de nition“whic¸ãh“is“called“ÎendingŽ¡‘'¿¬c–ÿ}'o“de².‘ÉÁEnding–r¨cošGde“can“b˜e“anš¸ãy“kind“of“sequence“of“ÇC‘r_²statemen˜ts.‘ÉÁThey“will“bGeŽ¡‘'¿¬executed–Îafter“²the“attribute“de nition“has“bGeen“put“together“and“Îb–ÿ}'efor“e–²the“ nalŽ¡‘'¿¬tok•¸ãen›Ðìiden“ti er˜id˜returned.‘äŒSo˜in˜e ect˜y“ou˜y“ourself˜ma“y˜pla“y˜GoGd˜and˜return˜aŽ¡‘'¿¬tok•¸ãen›/ˆiden“ti er˜y“ourself.‘_The˜follo“wing˜extract˜from˜a˜formatted˜tok“en˜ le˜is˜anŽ¡‘'¿¬example:ަ‘'¿¬È[a-zA-Z][a-zA-Z0-9]*‘îID›ÿô{–?ý**“}˜[“return(ID);“]ަ‘'¿¬²Here,‘the‘í1ÆreturnŽ‘%Ø’²statemenš¸ãt–í1is“executed“just“bGefore“the“prett˜yprin˜ting“scanner“itselfŽ¡‘'¿¬returns–¿the“ÈID‘‹²tokš¸ãen,‘Qso“here“y˜ou“could“lea˜v˜e“the“ending“coGde“a˜w˜a˜y“and“nothingŽ¡‘'¿¬wš¸ãould–¡ƒbGe“c˜hanged.‘VPBut“of“course,‘´Žy˜ou“could“put“an“ÆifŽ‘ øY²statemen˜t“there“and“returnŽ¡‘'¿¬something–@Oelse“as“yš¸ãou“wish.‘jÅThe“sym˜bGolic“names“of“all“the“tok˜ens“ma˜y“bGe“accessedŽ¡‘'¿¬with–UUthe“coGde“parts“simply“bš¸ãy“their“names“y˜ou“ga˜v˜e“them.Ž¡‘6¿¬No•¸ãw›UUy“ou˜migh“t˜w“onder,˜what˜the˜sequenceަ‘'¿¬È[a-zA-Z][a-zA-Z0-9]*–îID“[–?ýreturn(ID);“]ަ‘'¿¬²w•¸ãould›0'mean.‘Ž¡‘'¿¬#include"attr.h"Ž¡¡‘'¿¬class–?ýPscan“{Ž¡‘'¿¬public:Ž¡‘2?¦Pscan(istream*)‘?ý{};Ž¡‘2?¦~Pscan()‘?ý{};Ž¡‘2?¦virtual–?ýint“scan(Attribute**)“=“0;Ž¡‘'¿¬};ަ‘'¿¬²A‘NOPretzel–Nscanner“m¸ãust“bšGe“asso˜ciated“with“an“ÇCŸÿ²++Ž‘ÜËinput“stream“ob‘Ž8ject“that“isŽ¡‘'¿¬passed–»‰to“the“constructor“of“the“class.‘¤bThe“scanner“will“read“c¸ãharacters“from“thisŽ¡‘'¿¬input–stream“when“scanning.‘IThe“actual“scanning“if“pGerformed“inside“the“Îsc‘ÿ}'anŽŽ¡‘'¿¬²mem¸ãbšGer–£Ôfunction.‘]DIt's“return“co˜des“are“inš¸ãtegers“and“iden˜tify“the“tok˜en“that“it“hasŽ¡‘'¿¬just–UUscanned.‘qÇIf“the“input“is“empt¸ãy‘ÿ*ª,“it“returns“0.Ž¡‘6¿¬The–*psubšGclass“that“Pretzel“pro˜duces“will“alw•¸ãa“ys–*pb˜e“a“sub˜class“of“the“ab˜o•¸ãv“e‘*pclass.Ž¡‘'¿¬It's–UUin¸ãterface“is“similar:ަ‘'¿¬Èclass–?ýPSCAN_NAME“:“public“Pscan“{Ž¡‘'¿¬public:Ž¡‘2?¦PSCAN_NAME(istream*);Ž¡‘2?¦~PSCAN_NAME();Ž¡‘2?¦int‘?ýscan(Attribute**);Ž¡‘'¿¬};ަ‘'¿¬²The–y©name“of“the“generated“class“is“ÈPSCAN‘¡E‰ff&fŽ‘Ç«NAME‘y ²b¸ãy“default“and“has“to“bGe“rede nedŽ¡‘'¿¬using–UUpreproGcessor“macros,“suc¸ãh“as“for“exampleަ‘'¿¬È#define–?ýPSCAN_NAME“Pscan_for_pascalަ‘'¿¬²By––1default“the“name“of“the“deriv¸ãed“subšGclass“will“b˜e“ÈPpscan².‘2A‘–header“ le“con¸ãtainingŽ¡‘'¿¬the–#Wderivš¸ãed“scanner“class“could“loGok“lik˜e“this“(b˜y“default“the“header“ le“is“calledŽ¡‘'¿¬ÈPpscan.h²).‘qÇNote–UUthat“there“is“no“precaution“against“double“inclusion.ަ‘'¿¬È/*–?ýheader“file“for“a“prettyprinting“scanner“*/Ž¡¡‘'¿¬/*–?ýNB:“This“file“is“NOT“protected“against“double“inclusion!“*/Ž¡¡‘'¿¬#include–?ý"Pscan.h"“//“include“abstract“base“classŽ¡¡‘'¿¬#ifndef‘?ýPSCAN_NAMEŽ¡‘'¿¬#define–?ýPSCAN_NAME“PpscanŽ¡‘'¿¬#endifŽ¡¡‘'¿¬class–?ýPSCAN_NAME“:“public“Pscan“{ŽŽŽŒ‹ˆ ½\È ýN£8‘63ײ28’·ÇÀÃCHAPTER–UU3.‘ªªPRETZEL“HA¸ãCKINGŽŽ ˜G ý„‘63×Èpublic:ޤ ‘@³ÑPSCAN_NAME(istream*);Ž¡‘@³Ñ~PSCAN_NAME();Ž¡‘@³Ñint‘?ýscan(Attribute**);Ž¡‘63×};Ž©Z|‘63ײThis–â×is“exactly“the“default“header“ le“that“y¸ãou“can“ nd“in“the“Èinclude“²directoryŽ¡‘63×of–½the“Pretzel“distribution.‘©$If“Pretzel“is“installed“on“yš¸ãour“system,‘×y˜ou“should“ ndŽ¡‘63×this–Ðd le“(and“the“header“ le“for“the“abstract“base“class)“in“the“global“Pretzel“includeŽ¡‘63×directory‘UUtoGo.Ÿü^ÿ±3ŽŽŽŸl\‘63×Í3.2.2Ž‘_s×The›€Prett• yprin“ting˜P“arserŽŸuT‘63ײThe–Kinš¸ãterface“to“the“prett˜yprin˜ting“parser“is“similar“in“structure“to“the“prett˜yprin˜tingŽ¡‘63×scanner.‘qÇW‘ÿ*ªe›UUha•¸ãv“e˜an˜abstract˜base˜class˜called˜ÈPparse˜²that˜has˜this˜in“terface:ަ‘63×È#includeŽ¡‘63×#include"attr.h"Ž¡‘63×#include"output.h"Ž¡¡‘63×class–?ýPparse“{Ž¡‘63×public:Ž¡‘@³ÑPparse()‘?ý{};Ž¡‘@³Ñ~Pparse()‘?ý{};Ž¡‘@³Ñvirtual–?ýint“prettyprint(istream*,“ostream*)“=“0;Ž¡‘@³Ñvirtual–?ýint“prettyprint(istream*,“Output*)“=“0;Ž¡‘63×};ަ‘63ײThere–T}are“the“usual“functions“to“create“and“destroš¸ãy“a“prett˜yprin˜ting“parser“plusŽ¡‘63×an›’èo•¸ãv“erloaded˜virtual˜mem“bGer˜function˜Îpr‘ÿ}'ettyprintŽ‘2Dz.‘*The˜normal˜use˜of˜Îpr‘ÿ}'ettyprintŽŽ¡‘63ײuses–,ÇCŸÿ²++Ž‘hinput“and“output“streams.‘xKIt“reads“from“an“input“streams“and“writesŽ¡‘63×prett•¸ãyprin“ted–UUcoGde“to“the“output“stream.Ž¡‘E3×The–>Ñsecond“vš¸ãersion“of“this“mem˜bšGer“has“an“ÎOutputŽ‘%˜@²class“p˜oin¸ãter“as“second“argu-Ž¡‘63×menš¸ãt.‘šÙThis–¸[is“a“v˜ersion“for“expGerts.‘šÙSee“section“3.6“for“an“example“ho˜w“to“utilizeŽ¡‘63×this.Ž¡‘E3×The›Å­prett•¸ãyprin“ting˜parser˜class˜whic“h˜is˜actually˜generated˜is˜again˜a˜subGclass˜ofŽ¡‘63×this–*jabstract“base“class.‘cyIt's“name“ma¸ãy“bšGe“rede ned“using“ÇC‘*_²prepro˜cessor“macros.ަ‘63×Èclass–?ýPPARSE_NAME“:“public“Pparse“{Ž¡‘63×public:Ž¡‘@³ÑPPARSE_NAME();Ž¡‘@³Ñ~PPARSE_NAME();Ž¡‘@³Ñint–?ýprettyprint(istream*,“ostream*);Ž¡‘@³Ñint–?ýprettyprint(istream*,“Output*);Ž¡¡‘@³Ñvoid‘?ýdebug_on();Ž¡‘@³Ñvoid‘?ýdebug_off();Ž¡‘63×};ަ‘63ײThe›Ýt•¸ãw“o˜extra˜functions˜Îdebug‘‰ffŽ‘®onŽ‘-~ù²and˜Îdebug‘‰ffŽ‘®o Ž‘/\²enable˜and˜disable˜debugging˜out-Ž¡‘63×put.‘JÿDebugging–àüoutput“giv¸ães“an“indication“what“the“scanner“returns“and“what“kindŽ¡‘63×of–UUrules“the“parser“is“reducing.‘qÇIt“is“really“a“lot“of“information.Ÿü^ÿ±4ŽŽŽ¡‘E3ײAs–`yš¸ãou“can“see,‘bÂthe“name“of“the“generated“class“is“ÈPPARSE‘¡E‰ff&fŽ‘Ç«NAME‘`²b˜y“default“andŽ¡‘63×has–UUto“bšGe“rede ned“using“prepro˜cessor“macros,“suc¸ãh“as“for“exampleŽ‘63ןk‰ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»This–ÕXdirectory“will“usually“b‘ "5Ÿý-:¼4ŽŽŽ‘LÜ»The–¥>information“proÃŽvided“using“the“Ï-d“»option“of“Ïpretzel-it“»program“comes“from“using“theseŽŸ €functions–ÕX(see“section“2.3.5).ŽŽŽŒ‹‹ ½\È ýN£8‘'¿¬Ã3.3.‘ÇBUILDING–UUA“PRETZEL“PRETTYPRINTER“BY“HAND‘G$%²29ŽŽ ˜G ý„‘2?¦È#define–?ýPPARSE_NAME“Prettyprinter_for_pascalޤCÅ‘'¿¬²By–Ê÷default“the“name“of“the“deriv¸ãed“subšGclass“will“b˜e“de ned“as“ÈPpparse“²(note“theŽ© ‘'¿¬three–UU`p's).‘qÇThis“is“the“default“header“ le“for“the“generated“parser:Ž¡‘'¿¬È/*–?ýheader“file“for“a“prettyprinting“parser“*/ަ¦‘'¿¬/*–?ýNB:“This“file“is“NOT“protected“against“double“inclusion!“*/ަ¦‘'¿¬#include–?ý"Pparse.h"“//“include“abstract“base“classަ¦‘'¿¬#ifndef‘?ýPPARSE_NAMEަ‘'¿¬#define–?ýPPARSE_NAME“Ppparseަ‘'¿¬#endifަ¦‘'¿¬class–?ýPPARSE_NAME“:“public“Pparse“{ަ‘'¿¬public:ަ‘2?¦PPARSE_NAME();ަ‘2?¦~PPARSE_NAME();ަ‘2?¦int–?ýprettyprint(istream*,“ostream*);ަ‘2?¦int–?ýprettyprint(istream*,“Output*);ަ¦‘2?¦void‘?ýdebug_on();ަ‘2?¦void‘?ýdebug_off();ަ‘'¿¬};Ž¡‘'¿¬²This–Ï le“resides“in“the“Èinclude“²directory“of“the“Pretzel“distribution“and“togetherަ‘'¿¬with–ÛÇthe“header“of“the“abstract“base“class“is“also“is“found“in“the“Pretzel“Èincludeަ‘'¿¬²directory–UUof“the“system“(if“Pretzel“is“installed).ŽŸž•‘'¿¬Í3.2.3Ž‘Pÿ¬ExampleŽŸuT‘'¿¬²A–UUminimal“ le“that“utilizes“a“Pretzel“prett•¸ãyprin“ter–UUcould“loGok“lik¸ãe“this:Ž¡‘'¿¬È#include‘?ýަ‘'¿¬#include‘?ý"Ppparse.h"ަ¦‘'¿¬int–?ýmain“()“{ަ‘<¿ Ppparse‘?ýprettyprinter;ަ‘<¿ prettyprinter.prettyprint(&cin,&cout);ަ‘<¿ return(0);ަ‘'¿¬}Ž¡‘'¿¬²Firstly‘ÿ*ª,‘öthe–Õßactual“prett•¸ãyprin“ter–Õßclass“is“included.‘óeThen“w¸ãe“declare“a“simple“pret-ަ‘'¿¬t•¸ãyprin“ter–cmand“simply“call“Îpr‘ÿ}'ettyprintŽ‘2—™².‘œHere,‘fóthe“input“and“output“streams“are“con-ަ‘'¿¬nected–ªto“the“standard“input“and“the“standard“output.‘pIf“this“ÎmainŽ‘ Ó²routine“isަ‘'¿¬compiled–°Îand“link¸ãed“with“the“ob‘Ž8jects“proGduced“from“the“output“of“Pretzel,‘¬theަ‘'¿¬prett•¸ãyprin“ter–æwill“wš¸ãork“as“spGeci ed“in“the“t˜w˜o“input“ les.‘L¬The“prett˜yprin˜ting“parserަ‘'¿¬inš¸ãternally–UUcalls“the“prett˜yprin˜ting“scanner“b˜y“its“default“in˜terface.ŽŸ ²#‘'¿¬Ì3.3Ž‘L¦Building–ffa“Pretzel“prett•ŒÌyprin“ter›ffb“y˜HandŽŸç‘'¿¬²If–¡yš¸ãou“need“to“proGduce“a“prett˜yprin˜ting“moGdule“b˜y“hand“y˜ou'll“ha˜v˜e“to“directlyަ‘'¿¬in•¸ãv“ok“e›”tPretzel,–ä; ex,“Bison˜and˜y•¸ãour˜ÇCŸÿ²++Ž‘"°compiler˜in˜the˜righ“t˜order.‘/#T‘ÿ*ªo˜easeަ‘'¿¬this,‘"çy¸ãou–Æ—can“use“the“ÈMakefile“²in“the“ÇP‘ÿ ascal“²subGdirectory“of“the“distributionަ‘'¿¬(Èlanguages/pascal²).ŽŽŽŒ‹—a ½\È ýN£8‘63ײ30’¶«NÃCHAPTER–UU3.‘ÇPRETZEL“HA¸ãCKINGŽŽ ˜G ý„‘E3ײT‘ÿ*ªo–r)proGduce“(only)“the“prett•¸ãyprin“ting–r)parser“from“the“ le“Èpascal.fg“²for“example,ޤ ‘63×yš¸ãou–UUcould“t˜ypGe“the“follo˜wing:Ž©áÙ‘;sÔÈ$–?ýpretzel“-g“pascalŽ¡‘63×This–?ýis“pretzel,“version“2.0.Ž¡‘63×Processing–?ýthe“formatted“grammar“file“(pascal.fg“->“pascal.y).Ž¡‘63×No–?ýerrors“found.Ž¡‘;sÔ$–?ýbison“-d“pascal.yŽ¡‘63×pascal.y–?ýcontains“21“shift/reduce“conflicts.Ž¡‘;sÔ$–?ýmv“pascal.tab.h“ptokdefs.hŽ¡‘;sÔ$–?ýg++“-c“-I$PRETZEL_INCLUDE“-g“pascal.lex.cަ‘63ײW‘ÿ*ªe–Ðassume“that“the“ÈPRETZEL‘¡E‰ff&fŽ‘Ç«INCLUDE‘Ïè²en•¸ãvironmen“t–Ðv‘ÿqÇariable“pGoin¸ãts“to“the“PretzelŽ¡‘63×include–Ídirectory‘ÿ*ª.‘ñ/The“È-d“²option“of“Bison“will“proGduce“a“tok¸ãen“header“ le“thatŽ¡‘63×the–ògscanner“expGects“(the“scanner“mš¸ãust“kno˜w,‘¬whic˜h“tok˜ens“the“parser“a˜w˜aits“andŽ¡‘63×whic•¸ãh››«tok“en˜coGdes˜they˜ha“v“e).‘DÈThe˜scanner˜expGects˜these˜de nitions˜under˜theŽ¡‘63×name‘UUÈptokdefs.h².Ž¡‘E3×The›ÛŠabGo•¸ãv“e˜sequence˜of˜commands˜should˜lea“v“e˜a˜Èpascal.tab.o˜² le˜in˜y“ourŽ¡‘63×directory‘ÿ*ª.‘i„This–§éis“the“ob‘Ž8ject“coGde“of“the“prett•¸ãyprin“ting–§éparser“with“the“defaultŽ¡‘63×in¸ãterface–ʸ(i.e.“the“generated“class'“name“is“ÈPpparse“²and“is“declared“in“the“includeŽ¡‘63× le–tnÈPpparse.h²).‘ÏY‘ÿ*ªou“can“noš¸ãw“use“this“prett˜yprin˜ter“in“y˜our“o˜wn“programs:‘¯ùb˜yŽ¡‘63×including–ithe“header“ le“the“prett•¸ãyprin“ter–iclass“will“bGecome“visible;‘©sb¸ãy“linking“theŽ¡‘63×ob‘Ž8ject–û¸with“yš¸ãour“o˜wn“program“y˜ou'll“get“y˜our“executable.‘Sè(Note“that“y˜ou'll“need“toŽ¡‘63×proš¸ãvide–Ýøa“prett˜yprin˜ting“scanner“y˜ouself“in“this“case“or“simply“proGduce“a“suitableŽ¡‘63×one–UUin“a“similar“w•¸ãa“y–UUusing“Pretzel.)ŽŸ Ô*‘63×Ì3.4Ž‘[:Obtaining–ffa“Pretzel“Prett•ŒÌyprin“ting‘ffMos3duleŽŸç‘63ײIn– nthe“preceding“section“I‘ @ha•¸ãv“e– nexplained“hoš¸ãw“to“proGduce“a“Pretzel“prett˜yprin˜terŽ¡‘63×b•¸ãy›§^hand.‘gâNo“w˜w“e'll˜see˜ho“w˜y“ou˜can˜c“hange˜the˜default˜in“terface˜of˜the˜proGducedŽ¡‘63×prett•¸ãyprin“ting–UUscanner“and“parser.ŽŸÀœ‘63×Í3.4.1Ž‘_s×The›€Prett• yprin“ting˜ScannerŽŸuT‘63ײSa•¸ãy‘ÿ*ª,‘Öíy“ou–½need“a“prett•¸ãyprin“ting–½scanner“class“called“ÎF‘ÿ;¼o–ÿ}'osc“anŽ‘* y²in“a“header“ le“calledŽ¡‘63×ÈFooscan.h².‘8üAll–ªóyš¸ãou“ha˜v˜e“to“do“is“to“mak˜e“a“cop˜y“of“the“default“header“ le“ÈPpscan.hŽ¡‘63ײ(whic•¸ãh›{Ty“ou˜can˜ nd˜in˜the˜Pretzel˜include˜directory),‘¦îc“hange˜its˜name˜to˜ÈFooscan.h².Ž¡‘63×Then–UUyš¸ãou“ha˜v˜e“to“c˜hange“the“one“single“Æ#de neŽ‘-õH²statemen˜t“therin,“i.e.“instead“ofަ‘63×È#ifndef‘?ýPSCAN_NAMEŽ¡‘63×#define–?ýPSCAN_NAME“PpscanŽ¡‘63×#endifަ‘63ײy•¸ãou'll›UUha“v“e˜to˜writeަ‘63×È#define–?ýPSCAN_NAME“Fooscanަ‘63ײWithin–G3yš¸ãour“formatted“tok˜en“ le,‘Jy˜ou'll“ha˜v˜e“to“tie“in“the“same“de nition“lik˜e“this:ަ‘63×È%{Ž¡‘63×#define–?ýPSCAN_NAME“FooscanŽ¡‘63×%}ަ‘63ײIt–¯[is“impšGortan¸ãt“that“this“text“app˜ears“in“the“declarations“section“of“the“formattedŽ¡‘63×scanner–UU le,“i.e.“bšGefore“the“ rst“line“that“con¸ãtains“the“double“p˜ercen¸ãt“sign“`È%%²'.Ž¡‘E3×Compiling–/¿and“linking“the“source“proGduced“bš¸ãy“Pretzel“and“ ex“y˜ou'll“get“theŽ¡‘63×ob‘Ž8ject–€ïcoGde“that“conš¸ãtains“the“desired“prett˜yprin˜ting“scanner.‘ô–The“scanner“expGectsŽŽŽŒ‹¡8 ½\È ýN£8‘'¿¬Ã3.5.‘ÇMUL‘ÿ*ªTIPLE–UUPRETZEL“MODULES“IN“THE“SAME“PR¸ãOGRAM‘)ùu²31ŽŽ ˜G ý„‘'¿¬to–©æ nd“a“tok¸ãen“header“ le“under“the“default“name“Èptokdefs.h“²with“de nitions“ofޤ ‘'¿¬the–symš¸ãbGolic“names“and“tok˜en“coGdes“of“the“tok˜ens“it“should“bGe“able“to“scan.‘\`EitherŽ¡‘'¿¬yš¸ãou–NâproGduce“this“ le“b˜y“hand“or“y˜ou“let“Bison“do“the“job“for“y˜ou“(using“the“È-dŽ¡‘'¿¬²option–ç)if“yš¸ãou“ha˜v˜e“a“prett˜yprin˜ting“grammar).‘'CLoGok“in˜to“a“standard“Èptokdefs.hŽ¡‘'¿¬² le–Æ to“see“what“it“should“conš¸ãtain.‘ÃéThe“name“of“the“tok˜en“header“ le“Èptokdefs.hŽ¡‘'¿¬²maš¸ãy–µalso“bGe“c˜hanged.‘ÄçY‘ÿ*ªou“ha˜v˜e“to“de ne“the“ÈPTOKDEFS‘¡E‰ff&fŽ‘Ç«NAME‘‚²macro“within“y˜ourŽ¡‘'¿¬formatted–UUtokš¸ãen“ le“lik˜e“this:Ž©^‘'¿¬È%{Ž¡‘'¿¬#define–?ýPTOKDEFS_NAME“"fooscantoks.h"Ž¡‘'¿¬%}ަ‘'¿¬²Noš¸ãw–o_the“scanner“will“include“the“ le“Èfooscantoks.h“²and“loGok“for“tok˜en“coGde“de -Ž¡‘'¿¬nitions–#Úin“there.‘aI(Again,‘-Àthis“rede nition“m¸ãust“bGe“in“the“declarations“section“of“theŽ¡‘'¿¬formatted–UUtok¸ãen“ le.)ŽŸÛx‘'¿¬Í3.4.2Ž‘Pÿ¬The›€Prett• yprin“ting˜P“arserŽŸuT‘'¿¬²Changing–³0the“inš¸ãterface“of“the“prett˜yprin˜ting“parser“w˜orks“in“a“similar“w˜a˜y“as“justŽ¡‘'¿¬explained–#Sfor“the“prett•¸ãyprin“ting–#Sscanner.‘ÛÁThe“di erences“lie“in“the“macro“namesŽ¡‘'¿¬that›UUha•¸ãv“e˜to˜bGe˜rede ned.Ž¡‘6¿¬The–}Xname“of“the“derivš¸ãed“prett˜yprin˜ting“parser“class“is“ÈPPARSE‘¡E‰ff&fŽ‘Ç«NAME².“If“y˜ou“sa˜yŽ¡‘'¿¬in–UUthe“de nitions“section“of“the“formatted“grammar“ le“for“exampleަ‘'¿¬È%{Ž¡‘'¿¬#define–?ýPPARSE_NAME“FooppŽ¡‘'¿¬%}ަ‘'¿¬²then–î…yš¸ãour“prett˜yprin˜ter“class“will“bGe“called“ÈFoopp².‘=XIn˜ternally“it“expGects“the“pret-Ž¡‘'¿¬t•¸ãyprin“ting–°Yscanner“with“it's“default“in¸ãterface“(i.e.“under“the“names“ÈPpscan“²for“theŽ¡‘'¿¬class–Øvand“Èptokdefs.h“²for“the“tokš¸ãen“header“ le).‘û*If“y˜ou“rede ne“the“same“macrosŽ¡‘'¿¬as–³in“the“formatted“tokš¸ãen“ le,‘then“y˜ou“rede ne“the“in˜terface“under“whic˜h“the“pret-Ž¡‘'¿¬t•¸ãyprin“ter–v"expGects“the“scanner.‘Ô.So“lines“likš¸ãe“these“in“the“formatted“grammar“w˜ouldŽ¡‘'¿¬urge–UUthe“prett•¸ãyprin“ter–UUto“use“a“ÈFooscan“²class“ob‘Ž8ject“for“scanning:ަ‘'¿¬È%{Ž¡‘'¿¬#define–?ýPPARSE_NAME“FooppŽ¡‘'¿¬#define–?ýPSCAN_NAME“FooscanŽ¡‘'¿¬%}ŽŸ ï‘'¿¬Ì3.5Ž‘L¦Multiple–sPretzel“Mos3dules“in“the“same“Pro-ŽŸ‘L¦gramŽŸç‘'¿¬²Using–{m¸ãultiple“Pretzel“mošGdules“within“a“single“program“has“b˜een“greatly“simpli edŽ¡‘'¿¬b•¸ãy›>in“troGducing˜the˜ob‘Ž8ject˜orien“ted˜in“terface˜that˜has˜bGeen˜explained˜in˜section˜3.2.Ž¡‘'¿¬The–Émain“thing“is“to“cš¸ãhange“the“names“of“the“t˜w˜o“scanners/parsers“proGduced“b˜yŽ¡‘'¿¬Pretzel–Çéto“something“distinct“and“then“to“compile“and“link“then“together.‘ɃThat'sŽ¡‘'¿¬the‘UUtheory‘ÿ*ª.Ž¡‘6¿¬But–“«there's“a“problem“here:‘òthe“scanners“and“parsers“proGduced“b¸ãy“ ex“and“BisonŽ¡‘'¿¬conš¸ãtain–Œa“couple“of“global“v‘ÿqÇariables“whose“names“will“clash“when“y˜ou“try“to“linkŽ¡‘'¿¬them–©Dtogether.‘8mThis“maš¸ãy“bGe“circum˜v˜en˜ted“b˜y“using“spGecial“options“of“ ex“and“BisonŽ¡‘'¿¬to–¼µcš¸ãhange“the“pre x“of“these“globals“when“a“scanner/parser“is“built.‘§çAs“I‘¼šha˜v˜en'tŽ¡‘'¿¬needed–Ä×this“feature“in“the“past“(but“only“tested“it),‘á½I‘IJha•¸ãv“en't–Ä×prepared“an“additionalŽ¡‘'¿¬option–,Ìto“Èpretzel-it“²to“do“this“in“a“nice“and“easy“w•¸ãa“y‘ÿ*ª.‘dDA“t–,Ìthe“momenš¸ãt“y˜ou'll“stillŽ¡‘'¿¬ha•¸ãv“e–rto“consult“the“man¸ãual“pages“Èflex(1)²,‘‰úÈflexdoc(1)“²and“Èbison(1)“²for“details.ŽŽŽŒ‹ ® ½\È ýN£8‘63ײ32’¶«NÃCHAPTER–UU3.‘ÇPRETZEL“HA¸ãCKINGŽŽ ˜G ý„‘63ײIf–!òthis“is“a“feature“yš¸ãou“need,‘,9tell“me“and“I'll“add“it“to“Èpretzel-it“²(see“also“c˜hapterޤ ‘63×6,–UU\F›ÿ*ªuture“W˜ork").Ž© _t‘E3×Another–pthing“that“sounds“inš¸ãteresting,‘vËbut“that“I‘pha˜v˜e“not“tested“y˜et,‘vËis“to“useŽ¡‘63×sevš¸ãeral–binstances“of“a“single“prett˜yprin˜ter“class“proGduced“b˜y“Pretzel“in“the“sameŽ¡‘63×program.‘÷"If–Éyš¸ãou“ha˜v˜e“ev˜er“tried“it,‘ŒæI'm“v˜ery“in˜terested“in“y˜our“results“(see“c˜hapterŽ¡‘63×6,–UU\F›ÿ*ªuture“W˜ork"“again).ŽŸ# 1‘63×Ì3.6Ž‘[:Prett•ŒÌyprin“ting–fffor“non-LŸüû+‘ú+ÆAŽŽn¹ÌT‘ýL¨Ÿ32EŽ‘èdXiansŽŸ˜À‘O3Ù²\Of–À?course“ÈCWEAVE‘À²doGes“visual“formatting,‘Þat“least“for“the“part“that“can-Ž¡‘O3Ùnot–ÞbšGe“left“to“b˜e“visually“formatted“b¸ãy“T‘þU>Ÿ'EŽ‘ãxX:‘KŒit“issues“forced“line“breaks,Ž¡‘O3Ùexplicit–}cš¸ãhanges“of“inden˜tation“lev˜el“etc.‘¯@The“logical“markup“is“reallyŽ¡‘O3Ùconš¸ãtained–ñ#in“the“source“doGcumen˜t,‘and“not“(fully)“in“the“in˜termediateŽ¡‘O3Ù le–¦ÖproGduced“bš¸ãy“ÈCWEAVE².“Ho˜w˜ev˜er“ÈCWEAVE‘¦Á²doGes“not“do“complete“visualŽ¡‘O3Ùformatting:‘®Tfor–óœinstance“manš¸ãy“sym˜bGols“lik˜e“opšGerators“are“pro˜duced“asŽ¡‘O3Ùmacros,‘h½so–1¨that“yš¸ãou“can“easily“c˜hange“their“appGearance“b˜y“o˜v˜erridingŽ¡‘O3Ùthe–üGdefault“de nitions,‘&and“breaking“of“long“lines“is“also“left“to“T‘þU>Ÿ'EŽ‘ãxX'sŽ¡‘O3Ùline–UUbreaking“algorithm."ŽŸ¾è‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[60Ž‘ ]ŽŸ}Ï‘63×Pretzel–©öwš¸ãas“build“with“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“in“mind,‘¿but“this“doGesn't“necessarily“mean“that“y˜ouŽ¡‘63×are–Mrestricted“to“using“this“as“bacš¸ãk“end“of“y˜our“prett˜yprin˜ter.‘YThrough“the“w˜a˜yŽ¡‘63×that–¡œPretzel“wš¸ãas“designed,‘ô®it“is“quite“easy“to“extend“it“to“w˜ork“with“an˜y“otherŽ¡‘63×markup–Ôformatting“system.‘FßHo•¸ãw“ev“er,‘î[if›Ôy“ou˜are˜opting˜for˜immediate˜screen˜outputŽ¡‘63×or–Athings“likš¸ãe“ÇHTML²,“y˜ou're“not“lost“either.‘]ÀFirst,‘%Ew˜e'll“see“ho˜w“to“handle“the“ rstŽ¡‘63×case,–UUand“then“let's“go“and“loGok“at“things“lik¸ãe“ÇHTML².ŽŸø£‘63×Í3.6.1Ž‘_s×Other–€Markup“F‘þàormattersŽŸ&ù‘63ײInš¸ãternally‘ÿ*ª,‘«—all–šVpieces“of“coGde“that“handle“the“direct“output“of“c˜haracters“or“formatŽ¡‘63×commands–‹to“the“output“stream“are“encapsulated“in“a“ÇCŸÿ²++Ž‘@class“called“ÆOutputŽ‘(J÷².Ž¡‘63×The–Þinš¸ãterface“and“implemen˜tation“of“this“class“are“describGed“in“the“Ènoweb“²sourceŽ¡‘63× le–ÁÈoutput.nw“²in“the“Èoutput“²subšGdirectory“of“the“Pretzel“distribution.‘@^F‘ÿ*ªrom“lo˜okingŽ¡‘63×at–hBthis“ le,‘¬ýy¸ãou'll“see“that“there“is“an“abstract“base“class“ÆOutputŽ‘-w²and“that“theŽ¡‘63×standard–™Üclass,‘¿[whicš¸ãh“Pretzel“prett˜yprin˜ters“use,‘¿[is“the“ÆLatex‘°¡‰ffs4Ž–#Õcw®9eb‘°¡‰ffs4Ž“outputŽ‘dkC²classŸü^ÿ±5ŽŽ‘|s²,Ž¡‘63×a–’ subšGclass“of“ÆOutputŽ‘(Qý².‘'åIt“is“within“this“sub˜class“that“the“actual“translation“of“theŽ¡‘63×format–âÑcommand“Îfor–ÿ}'c“eŽ‘n²inš¸ãto“the“string“\È\pretzelforce{}²"“tak˜es“place“for“example.ަ‘E3×If–Ûyš¸ãou“are“going“for“something“lik˜e“T‘ÿ*ªro ,‘óßy˜ou“can“similarly“deriv˜e“a“new“subGclassŽ¡‘63×of‘XïÆOutputŽ‘+qѲ(for–Xïexample“bš¸ãy“cop˜ying“the“original“class)“and“simply“replace“the“textŽ¡‘63×bits–vÎlikš¸ãe“\È\pretzelindent²"“with“the“strings“appropriate“for“T‘ÿ*ªro .‘'šNo˜w,‘£Oy˜ou“ha˜v˜e“toŽ¡‘63×instruct–Føthe“generated“prett•¸ãyprin“ter–Fønot“to“use“the“default“(ÆLatex‘°¡‰ffs4Ž‘#Õcw®9ebŽ‘97P²-)“output,Ž¡‘63×but–‚"to“use“yš¸ãour“new“one.‘+aF‘ÿ*ªor“this“sak˜e,‘¬`the“second“v˜ersion“of“the“Îpr‘ÿ}'ettyprintŽ‘48p²mem˜bGerŽ¡‘63×function–sÛof“the“generated“prett•¸ãyprin“ter›sÛma“y˜bGe˜used˜(see˜section˜3.2,‘{|\The˜PretzelŽ¡‘63×Inš¸ãterface").‘ÓOSimply– ‚pass“an“ob‘Ž8ject“of“y˜our“new“output“class“to“the“function“andŽ¡‘63×the›°prett•¸ãyprin“ter˜will˜use˜it˜instead.‘‚ By˜deriving˜a˜new˜subGclass,‘ÆÏT‘ÿ*ªro ˜and˜LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxXŽ¡‘63×prett•¸ãyprin“ters›UUma“y˜co•Gexist˜p“eacefully‘ÿ*ª.ŽŸø£‘63×Í3.6.2Ž‘_s×Going–€for“ó.Œ-ø cmcsc10ÙHTMLŽŸ&ù‘63ײWhat–«iif“yš¸ãou“don't“ha˜v˜e“a“real“markup“formatting“system“at“hand“and“w˜an˜t“to“goŽ¡‘63×for–UUsomething“in“the“range“of“a“vt100“terminal,“line“prin¸ãter“or“ÇHTML“²page?Ž‘63ן Õü‰ff‰¬Ÿ J=‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»The–ÕXname“of“this“class“results“from“the“goal,“to“givšÃŽe“a“LŸþ¢#‘üð¡¼AŽŽ‘ ï»T‘þ•AŸ¸ãEŽ‘MX“ÏCWEB“»touc˜h“to“the“output“[57Ž‘€].ŽŽŽŒ‹!¼¨ ½\È ýN£8‘'¿¬Ã3.6.‘ÇPRETTYPRINTING–UUF¸ãOR“NON-LŸýó4‘üffó/¡8)Ïcmsl8ÚAŽŽx‘ÃT‘þU>Ÿ'EŽ‘ãxXIANS’ùé²33ŽŽ ˜G ý„‘6¿¬Bad–¢:news“is“that“yš¸ãou'll“ha˜v˜e“to“do“without“the“full“blo˜wn“format“commandޤ ‘'¿¬set.‘žºPropGer–dQin¸ãterpretation“of“the“line“breaking“commands“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘7Ï$²and“ÎoptŽ‘Ⅎ,‘htheŽ¡‘'¿¬commands‘$Îb‘ÿ}'ackupŽ‘%Ê\²and‘$Îno‘‰ffŽ‘®indentŽ‘2üá²cannot–$bGe“guaranš¸ãteed“in“these“cases.‘ÝóHo˜w˜ev˜er,Ž¡‘'¿¬go•Go“d–¥®news“is“that“the“Pretzel“distribution“conš¸ãtains“a“deriv˜ed“ÆOutputŽ‘, O²class“calledŽ¡‘'¿¬ÆAscii‘°¡‰ffs4Ž‘#ÕoutputŽ‘j ‘²that–®maš¸ãy“bGe“used“to“output“prett˜yprin˜ted“coGde“with“this“restrictedŽ¡‘'¿¬command–›set“to“the“screen“(or“to“anš¸ãy“device“suitable“for“ÇASCIJ«I‘›²c˜haracters).‘BþTheŽ¡‘'¿¬format–2§commands“that“cannot“bšGe“executed“prop˜erly“are“still“v‘ÿqÇalid,‘9–but“result“in“noŽ¡‘'¿¬actions–ÅBwhen“outputting“cošGde.‘ÁSee“the“ le“Èasciioutput.nw“²in“the“Èoutput“²sub˜di-Ž¡‘'¿¬rectory–UUof“the“Pretzel“distribution“for“details.Ÿü^ÿ±6ŽŽŽ‘'¿¬  5Éff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»An–õ†example“Ïnoweb“»prett•ÃŽyprin“ter–õ†that“emits“ÐHTML‘ô5»coš5[11Ž‘ ]“proš¸ãvide“go•Go“d–>5and“readable“in˜trošGductions“to“the“ eld,‘vwhile“the“pap˜er“b¸ãyŽ¡‘'¿¬Cordes–"Æand“Broš¸ãwn“[9Ž‘]“discusses“the“paradigm“and“the“b•Go“ok–"Æb˜y“Kn˜uth“[32Ž‘ ]“pro˜videsŽ¡‘'¿¬a–*collection“of“related“articles.‘0Concerning“Ènoweb²,‘·šthere“is“a“lot“of“go•Go“d‘*in¸ãtro“ductoryŽ¡‘'¿¬material–›Laš¸ãv‘ÿqÇailable“online“(see“for“example“the“Ènoweb“²home“page“[48Ž‘ ]).‘C­As“y˜ou“willŽ¡‘'¿¬need–N¹Ènoweb“²an•¸ãyw“a“y–N¹to“install“and“run“Pretzel,‘ƒ?it“is“a“go•Go“d–N¹idea“to“try“a“small“exampleŽ¡‘'¿¬noš¸ãw–…_if“y˜ou“are“unaquain˜ted“with“it.‘æLate“sections“will“need“detailed“kno˜wledgeŽ¡‘'¿¬abšGout–еthe“concepts“of“no•¸ãw“eb–еas“explained“in“the“original“pap˜er“b¸ãy“Ramsey“[50Ž‘ ]Ž¡‘'¿¬or–Þ&the“ultimate“reference“to“Ènoweb²'s“inš¸ãterior“b˜y“the“same“author“[47Ž‘ ].‘ ;The“ÈnowebŽ¡‘'¿¬²extensions–Ž‘of“Pretzel“are“still“vš¸ãery“m˜uc˜h“expGeriman˜tal“and“far“from“making“ÈnowebŽ¡‘'¿¬²as›UUpGo•¸ãw“erfull˜as˜language˜depGenden“t˜literate˜programming˜toGols.ŽŸ ²Ê‘'¿¬Ì4.1Ž‘L¦Prett•ŒÌyprin“ting–ffin“ó-߆µTff cmtt12Ønoweb“Ì{“HošŒÌw“it“w˜orksŽŸç‘@¿®²\They–cH[the“prett•¸ãyprin“ting–cH lters]“can“pšGerform“either“or“b˜oth“of“t•¸ãw“o‘cHtasks:ޤ#f‘L¿­¸ŽŽŽ‘V¿®²c•¸ãhoGose›UUfon“ts˜and˜glyphs˜to˜represen“t˜eac“h˜source˜tok“enŽŸ#f‘L¿­¸ŽŽŽ‘V¿®²c•¸ãhoGose›UUinden“tation˜and˜line˜breaks˜of˜y“our˜coGdeŽ¡‘@¿®I‘[î nd–\2these“features“of“more“cost“than“bšGene t“(except“p˜ossibly“whenޤ ‘@¿®preparing–UUfor“b•Go“ok–UUpublication),“but“lots“of“pGeople“lik¸ãe“them.ަ‘@¿®No•¸ãw“eb›³tak“es˜the˜reasonable˜p•Gosition˜that˜the˜programmer˜is˜the˜b“estŽ¡‘@¿®judge–^gof“where“to“put“the“line“breaks“and“hoš¸ãw“m˜uc˜h“to“inden˜t“coGde.Ž¡‘@¿®In–w*some“languages“(Miranda,–¿ŸHaskš¸ãell,“a˜wk,“Icon),“line–w*breaks“and/orŽ¡‘@¿®indenš¸ãtation–Ñcarry“meaning,‘$and“to“c˜hange“them“w˜ould“bGe“to“c˜hange“theŽ¡‘@¿®meaning–UUof“the“user's“program."ŽŽŸK’×lx35ŽŽŒ‹$Ôa ½\È ýN£8‘63ײ36’§RzÃCHAPTER–UU4.‘ªªPRETZEL“MEETS“ÈNOWEBŽŽ ˜G ý„‘O3Ù²Norman–UURamsey“[52Ž‘ ]ŽŸµ¸‘63×A‘…þprimary–†Ldesign“goal“in“devš¸ãeloping“Ènoweb“²w˜as“to“ha˜v˜e“a“literate“programmingޤ ‘63×tošGol–LÃthat“w¸ãas“simple“enough“to“learn“easily‘ÿ*ª,‘Nzand“also“suitable“for“easy“mo˜di cationŽ¡‘63×and–t~extensions.‘ÏAThis“second“goal“wš¸ãas“ac˜hiev˜ed“b˜y“it's“\pipGelined“arc˜hitec˜h˜ture"Ž¡‘63×[47Ž‘ ].‘;Inš¸ãternally–‹ÑÈnoweb“²con˜v˜erts“the“input“ les“in˜to“a“stream“of“items“whic˜h“|“lik˜eŽ¡‘63×in–Еa“pipšGeline“|“are“squeezed“through“sp˜ecial“programs“called“Î lters“²that“p˜erformŽ¡‘63×simple–å@transformations“on“these“data“items.‘!ˆThe“format“of“the“data“items“in“theŽ¡‘63×pipšGeline–g†is“called“the“\no•¸ãw“eb–g†pip˜eline“represenš¸ãtation"“whic˜h“in˜terested“readers“canŽ¡‘63×study–9win“detail“elsewhere“[47Ž‘ ].‘h}Devising“a“prett•¸ãyprin“ter–9wfor“Ènoweb“²means“building“aŽ¡‘63×prettš¸ãyprining–UU lter“for“it.‘qÇSuc˜h“a“ lter“can“then“bGe“inserted“in˜to“the“pipGeline.Ž©ï=‘63×Í4.1.1Ž‘_s×A–€ó1߆µT cmtt12Ünoweb“ÍPrett• yprin“ter–€for“ÙCŽŸÉà‘63ײIn–|†the“Ècontrib/noweb/cee.latex“²y¸ãou“can“ nd“the“de nitions“of“a“simple“pret-Ž¡‘63×t•¸ãyprin“ter–Ë{for“ÇC².“Change“in¸ãto“this“directory“and“loGok“at“the“ les“Ècee.ft“²and“Ècee.fg².Ž¡‘63×They–Ÿ~are“normal“Pretzel“input“ les“that“ha•¸ãv“e–Ÿ~bšGeen“mo˜di ed“slighš¸ãtly“to“w˜ork“withŽ¡‘63×Ènoweb².‘C˜Before–ÊÈw¸ãe“lošGok“at“these“mo˜di cations,‘æ~let's“try“to“build“a“Ènoweb“²prett•¸ãyprin“t-Ž¡‘63×ing–êz lter“ rst.‘N)T‘ÿ*ªo“do“this,‘ÿÙyš¸ãou“can“use“the“È-n“²option“of“Èpretzel-it“²in“the“follo˜wingŽ¡‘63×w•¸ãa“y:ޤˆJ‘63×Èpretzel-it–?ý-n“cee“prettyceeŽ¡‘63ײThis–îwill“proGduce“a“Ènoweb“²prett•¸ãyprin“ter–îcalled“Èprettycee“²in“the“curren¸ãt“directory‘ÿ*ª.Ÿü^ÿ±1ŽŽŽ¤ ‘63ײThis–—Ó lter“can“then“bGe“senš¸ãt“in˜to“action“using“the“È-filter“²option“of“Ènoweave².‘9@F‘ÿ*ªorŽ¡‘63×an–UUexample,“t¸ãypGe:ޤˆJ‘63×Ènoweave–?ý-delay“-filter“prettycee“ceetest.nw“>“ceetest.texŽ¡‘63ײThis–ëwill“mangle“the“Ènoweb“²input“ le“Èceetest.nw“²and“output“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“source“toޤ ‘63×Èceetest.tex².‘·óNoš¸ãw–l¹run“it“through“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“and“ha˜v˜e“a“loGok“at“the“result.Ÿü^ÿ±2ŽŽ‘ 4f²What“doŽ¡‘63×y¸ãou‘UUthink?ަ‘63×Í4.1.2Ž‘_s×W‘þàriting›€Prett• yprin“ting˜Grammars˜for˜ÜnowebŽŸÉà‘O3Ù²"The–Dmost“signi canš¸ãt“do˜wnsinde“of“not“using“ÈCWEB‘D{²is“lac˜k“of“coGde“pret-Ž¡‘O3Ùt•¸ãyprin“ting;‘Pho“w“ev“er,‘O¬after›NAprett“yprin“ting˜coGde˜for˜quite˜some˜time˜I‘N?gotŽ¡‘O3Ùtired–UUof“it“and“I“am“noš¸ãw“a“n˜u˜w˜eb“minimalist."ŽŸZÜ‘O3ÙPrzemek–UUKloso¸ãwski“[27Ž‘ ]ŽŸµ¸‘63×No•¸ãw,‘ÖZho“w–¶›do“the“Ècee.ft“²and“Ècee.fg“² les“di er“from“their“non-Ènoweb“²coun¸ãterparts?Ž¡‘63×F‘ÿ*ªrom–¤÷yš¸ãour“pGoin˜t“of“view,‘øßconsider“ev˜ery“coGde“c˜h˜unk“as“a“sepGerate“input“to“theŽ¡‘63×prett•¸ãyprin“ter›¿Èy“ou˜write.‘±!So˜the˜only˜things˜to˜note˜when˜building˜a˜prett“yprin“terŽ¡‘63×for–à˜Ènoweb“²is“that“yš¸ãou“ma˜y“ha˜v˜e“arbitrary“coGde“fragmen˜ts“instead“of“full“blo˜wnŽ¡‘63×programs–`or“functions,‘+and“that“c•¸ãh“unk–`uses“maš¸ãy“appGear“an˜ywhere“within“the“inputŽ¡‘63×coGde.ŽŸ -n‘E3×Chš¸ãunk–Úµuses“come“as“individual“lines“in˜to“the“prett˜yprin˜ter.‘æThese“lines“are“inŽ¡‘63×raš¸ãw–UUpipGeline“represen˜tation,“i.e.“loGok“something“lik˜e“this:ŽŸˆJ‘63×È@use–?ýFoo“BarŽ‘63ן‰ff‰¬Ÿ J=‘ "5Ÿý-:¼1ŽŽŽ‘LÜ»The–î,Ïnoweb“»extensions“of“Pretzel“mšÃŽust“ha˜v˜e“b‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»PšÃŽeople–êðwho“are“in˜terested“in“the“in˜ternals“of“this“opŸ'EŽ‘ãxX“stš¸ãyle“ le“as“w˜ell“asަ‘'¿¬the–+ le“Èpretzel-noweb.sty².‘c°It“is“impGortanš¸ãt“that“the“Ènoweb“²st˜yle“comes“bGefore“theަ‘'¿¬Èpretzel-noweb–^d²st¸ãyle,‘`¨bGecause“the“latter“rede nes“a“macro“from“the“prior“(see“alsoަ‘'¿¬section‘UU4.2).ަ‘6¿¬Y‘ÿ*ªou–úmaš¸ãy“debug“the“prett˜yprin˜ting“ lter“b˜y“setting“an“en˜vironmen˜t“v‘ÿqÇariableަ‘'¿¬called›=ÈPRETZEL‘¡E‰ff&fŽ–Ç«NOWEB‘¡E‰ff&fŽ“DEBUG‘ ²to˜the˜v–ÿqÇalue˜\Èon²".‘·An˜empt¸ãy˜v“alue˜will˜turn˜debugަ‘'¿¬information–Ü[o “again.‘ItThis“is“a“simple,‘ôbut“easy“to“use“methoGd“of“con¸ãtrolling“debugަ‘'¿¬output.‘qÇSuggestions–UUfor“impro•¸ãv“emen“ts–UUare“w¸ãelcome.ŽŸ\Ò‘'¿¬Í4.1.3Ž‘Pÿ¬Making–€the“Best“Use“of“ItŽŸuT‘@¿®²\The–š@one“area“where“language“depšGenden¸ãt“LP‘što˜ols“are“ahead“is“iden¸ãti erަ‘@¿®indexing,›<but–5ÐI‘5ÈsuspGect“that“for“ÇCŸÿ²++Ž‘Ž<,˜this“is“an“almost“impGossible“taskަ‘@¿®an•¸ãyw“a“y‘ÿ*ª."ŽŸD“‘@¿®Matthias–UUNeerac¸ãher“[42Ž‘ ]ŽŸVà‘'¿¬Ha¸ãving›këundersto•Go“d˜ho•¸ãw˜Ènoweb˜²prett“yprin“ters˜di er˜from˜normal˜Pretzel˜prett“yprin“t-ަ‘'¿¬ers,›]?it–(wis“easy“to“con•¸ãv“ert–(w les“in“either“direction.‘ë,But“no•¸ãw,˜w“e–(walso“get“languageަ‘'¿¬depGendenš¸ãt–ÀWinformation“within“the“prett˜yprin˜ter“nearly“for“free“and“w˜e“can“for“ex-ަ‘'¿¬ample–UUstart“to“build“an“index“of“iden¸ãti er“de nitions“and“uses.ަ‘6¿¬F‘ÿ*ªor–UUexample,“in“the“formatted“tokš¸ãen“ le,“y˜ou“could“write:Ž¡‘'¿¬È[a-zA-Z][a-zA-Z0-9_]*‘ÿôIDަ’ªÿa{"%\n@index–?ýuse“"“+“**“+“"\n"ަ’°?^"{\\it–?ý"‘ ú[escaped_underlines(yytext)]“"}"“}Ž¡‘'¿¬²Here,‘‹àev•¸ãery›€øiden“ti er˜will˜ nally˜bGe˜preceded˜b“y˜a˜line˜that˜will˜tell˜the˜indexer˜ofަ‘'¿¬Ènoweb–´Ð²abšGout“the“app˜earance“of“the“idenš¸ãti er“in“this“c˜h˜unk.‘ãÈcee.ft“²or“Èjava.fg²).˜The“prett•¸ãyprin“ting–ï lter“forŽ¡‘63×Ènoweb–x³²that“is“prošGduced“should“b˜e“called“Èpretty...‘Ûâ²with“the“dots“replaced“b¸ãy“theŽ¡‘63×programming–UUlanguage“name“(e.g.“Èprettycee“²or“Èprettyjava²).Ž¡‘E3×In–¼3the“dev•¸ãelopmen“t–¼3directories“yš¸ãou'll“ nd“spGecial“Ènoweb“² les“mean˜t“to“test“theŽ¡‘63×prett•¸ãyprin“ters,‘žnot–°to“bGe“of“anš¸ãy“programming“use.‘UThey“include“most“of“the“syn˜taxŽ¡‘63×constructs–• of“the“programming“language“in“question.‘1¯These“ les“are“vš¸ãery“instructiv˜eŽ¡‘63×when–Žbuilding“a“new“prett•¸ãyprin“ter–Žfor“no•¸ãw“eb–Žor“testing“one“that“yš¸ãou“ha˜v˜e“c˜hanged.ŽŸ!Ä‘63×Ì4.2Ž‘[:ProblemsŽŸç‘O3Ù²\I‘TÙthink–Uthe“problem“here“is“not“so“m•¸ãuc“h–Uthat“prett•¸ãyprin“ting–Uis“inheren¸ãtlyŽ¡‘O3Ùbad–;Ùas“that“manš¸ãy“languages“don't“bGene t“from“it“so“m˜uc˜h.‘iHÇAlgol“²andŽ¡‘O3ÙÇP‘ÿ ascal²,–Ü*I‘ÁbšGeliev¸ãe,“b˜ene t–Á2quite“a“bit“from“appropriate“prett•¸ãyprin“ting.Ž¡‘O3ÙThese–oèare“languages“where“yš¸ãou“write“out“a“lot“of“whole“w˜ords:‘¦í`bGegin',Ž¡‘O3Ù`end',– D`do',“`then'›Ä{.–ªª.“.‘o%Y‘ÿ*ªou˜get˜the˜idea.‘¿8Languages˜lik¸ãe˜ÇC‘IJand˜IconŽ¡‘O3ÙdepšGend–63a“lot“on“sym¸ãb˜olic“notation.‘bF‘ÿ*ªor“the“large“part,‘nkall“ÈCWEB‘5ù²do˜esŽ¡‘O3Ùis–£Hreplace“one“set“of“sym¸ãbšGols“with“another“that“some“p˜eople“happ˜enŽ¡‘O3Ùto›MÂprefer.‘[But,–‹Ýstill,“ÈCWEB‘M‚²puts˜reserv•¸ãed˜w“ords˜and˜de ning˜w“ords˜inŽ¡‘O3ÙbGoldface–aÊand“iden¸ãti ers“in“italics;‘hwhat“of“that?‘—%In“ÇP‘ÿ ascal²,‘dçdoing“thatŽ¡‘O3Ùhelps–׎mark“out“the“form“of“a“construct.‘øsIn“ÇC²,“on“the“other“hand,‘øtheŽ¡‘O3Ùconstructs–à}are“delimited“bš¸ãy“things“lik˜e“paren˜theses“and“braces,‘Gand“soŽ¡‘O3Ùputting–Qøthings“in“di erenš¸ãt“t˜ypšGefaces“do˜esn't“help“that“m•¸ãuc“h.‘p¨OK,‘QøÈCWEBŽ¡‘O3Ù²inden•¸ãti es,‘ŽÃbut›Py“ou˜don't˜need˜w“ea“v“e˜to˜do˜that;‘ÍsEmacs˜can˜do˜thatŽ¡‘O3Ùfor–m¥yš¸ãou,‘s¹or“y˜ou“can“do“it“y˜ourself,‘s¹and“the“w˜eb“source“will“bGene t“fromŽ¡‘O3Ùit.‘ #The–ßmain“thing“that“I‘Þ¹mighš¸ãt“w˜an˜t“from“Ènoweb“²but“don't“get“isŽ¡‘O3Ùtš¸ãypGesetting–-êof“commen˜ts,‘dand“I‘-²can“liv˜e“without“that“bGecause“I‘-²don'tŽ¡‘O3Ùneed–UUa“great“manš¸ãy“commen˜ts."ŽŸ‘O3ÙBarry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŸ‘63×Handling–lúof“commenš¸ãts“in“prett˜yprin˜ting“remains“an“unsolv˜ed“problem“to“date“(seeŽ¡‘63×section–%—5.2.5).‘âŒThis“is“partially“due“to“the“fact“that“that“commen¸ãts“can“crop“upŽ¡‘63×anš¸ãywhere–;¸in“the“coGde“and“that“they“themself“can“again“con˜tain“quoted“coGde.‘i=WithŽ¡‘63×Ènoweb–·ï²this“problem“isn't“so“sevš¸ãere,‘ЕbGecause“c˜h˜unks“mostly“do“not“con˜tain“a“lot“ofŽ¡‘63×commenš¸ãts–Êjas“they“are“mo˜v˜ed“to“the“doGcumen˜tation“parts“of“the“literate“program.Ž¡‘63×But–UUstill“a“nice“w•¸ãa“y–UUof“handling“commen¸ãts“needs“to“bGe“found.Ž¡‘E3×Also,‘Öquoted–¶+cošGde“in“do˜cumenš¸ãtation“c˜h˜unks“isn't“prett˜yprin˜ted.‘<¹This“is“partiallyŽ¡‘63×a–ÿJde cit“of“the“prett•¸ãyprin“ter–ÿJAPI‘ÿand“partially“a“structural“problem.‘o¥One“w¸ãouldŽ¡‘63×need›Ót•¸ãw“o˜distinct˜prett“yprin“ters˜to˜handle˜normal˜c“h“unk˜co•Gde˜and˜quoted˜co“deŽ¡‘63×sep•Gerately›¹èb“ecause˜y•¸ãou˜don't˜w“an“t˜to˜ha“v“e˜forced˜line˜breaks˜within˜doGcumen“tation.Ž¡‘E3×Another–—‡problem“arises“from“the“Ènoweb.sty“²LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“stš¸ãyle.‘8^The“en˜vironmen˜t“forŽ¡‘63×setting–¹.cošGde“naturally“is“rather“restrictiv¸ãe“and“a“macro“needs“to“b˜e“c¸ãhanged“in“orderŽ¡‘63×to–:½alloš¸ãw“the“Pretzel“macros“to“w˜ork“correctly‘ÿ*ª.Ÿü^ÿ±3ŽŽ‘²All“this“signals,‘sCthat“Pretzel“an“ÈnowebŽ¡‘63ײha•¸ãv“e–UUnot“bGecome“real“friends“yš¸ãet;“they“still“ha˜v˜e“to“w˜ork“on“their“relationship.Ž‘63ן;G‰ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»I'm–ÕXnot“a“T‘þ•AŸ¸ãEŽ‘MX“freak“after“all.‘Ç Thanks“to“Lee“WittenÃŽbŸ'EŽ‘ãxX,˜and“Standard“ML.“Some“pGeople“ha•¸ãv“eŽ¡‘@¿®made–?ûit“prett•¸ãyprin“t–?ûother“language,‘D@likš¸ãe“Icon“and“Ob‘Ž8ject-Orien˜ted“T‘ÿ*ªur-Ž¡‘@¿®ing.‘+ƒI‘‚Rha•¸ãv“en't–‚‡bGeen“o•¸ãv“erwhelmed›‚‡b“y˜the˜results,‘¬±but˜then˜I'm˜notoriouslyŽ¡‘@¿®dicult–UUto“conš¸ãvince“of“the“v‘ÿqÇalue“of“prett˜yprin˜ting."ŽŸ!+‘@¿®Norman–UURamsey“[51Ž‘ ]ŽŸ¥×‘'¿¬The–LHterm“Îpr‘ÿ}'ettyprinting“²means“the“rearrangemen¸ãt“of“a“program's“source“coGde“toŽ¡‘'¿¬illuminate–¥ƒit's“logical“structure“and“thš¸ãus“enhance“readabilit˜y‘ÿ*ª.‘bPThe“term“goGes“bac˜kŽ¡‘'¿¬to–eHenry“Ledgard“and“his“\Programming“Pro•¸ãv“erbs"›e[35Ž‘ ].‘!¬Prett“yprin“ting˜has˜bGecomeŽ¡‘'¿¬a–ß¿ eld“of“inš¸ãterest“bGecause“man˜y“of“toGda˜ys“pGopular“programming“languages“are“soŽ¡‘'¿¬called––/\free-format"“languages,‘¼jwhere“there“are“basically“no“column-pGosition“or“line-Ž¡‘'¿¬bGoundary–UUrestrictions“on“statemenš¸ãts,“declarations,“or“commen˜ts.Ž¡‘6¿¬As–ð©a“matter“of“fact,‘W}formatting“and“all“other“aspšGects“of“readabilit¸ãy“dep˜endŽ¡‘'¿¬hea¸ãvily– Ðon“pGersonal“taste“and“skill.‘•7This“has“lead“to“a“wide“range“of“suggestionsŽ¡‘'¿¬and–h9standards“concerning“the“formatting“of“programming“languages,‘lòespGecially“forŽ¡‘'¿¬the–q­ÇP‘ÿ ascal“²[23Ž‘ ]“language“[1Ž‘,“2Ž›q®,“3Ž˜,“6Ž˜,“10Ž› q¯,“16Ž˜,“18Ž˜,“20Ž˜,“34Ž˜,“37Ž˜,“45Ž˜,“40Ž˜].‘%åThe“consistency“ofŽ¡‘'¿¬these–äpropGosals“has“also“enabled“construction“of“automatic“formatting“algorithmsŽ¡‘'¿¬and–Œ toGols“that“are“usually“called“Îpr›ÿ}'ettyprinters‘^,²(or“Îindenting‘±Âpr˜o˜gr˜ams‘Ò!²).‘êIn“theŽ¡‘'¿¬literature–:general“examples“of“prett•¸ãyprin“ters›:ha“v“e˜bGeen˜presen“ted˜among˜others˜forŽ¡‘'¿¬the–­blanguages“ÇAlgol“²[39Ž› ,“59Ž‘ ­d],–ÎúPL/I‘­8[8Ž‘],“ÇLisp–­b²[15Ž˜,“19Ž› ­d,“65Ž˜,“66Ž˜],›ÎúAda“[43Ž‘ ],˜and“of“courseŽ¡‘'¿¬for–UUÇP‘ÿ ascal“²[21Ž‘ ,“22Ž› UW,“3Ž‘UV,“67Ž˜,“1Ž‘UV].Ž¡‘6¿¬Ho•¸ãw“ev“er,‘~àtec“hnological–v‘adv‘ÿqÇance“in“the“area“of“automatic“t¸ãypGesetting“has“led“toŽ¡‘'¿¬a–Æset“of“pšGo•¸ãw“erful–Æformatting“to˜ols“called“Îtyp›ÿ}'esetters²,‘ãor“Îtyp˜esetting‘systems²,‘ãof“whic¸ãhŽ¡‘'¿¬T‘þU>Ÿ'EŽ‘ãxX–9ÿ[30Ž‘ ]“is“maš¸ãybGe“the“most“apparen˜t“to“computer“scien˜tists.‘hªThese“toGols“allo˜w“theŽ¡‘'¿¬preparation–of“doGcumenš¸ãts“in“high“qualit˜y“suited“for“publication.‘*WAmong“the“featuresŽ¡‘'¿¬of–>]these“systems“are“automatic“line-“and“page-breaking,‘BõpšGo•¸ãw“erful‘>]macro-pro˜cessingŽ¡‘'¿¬facilities–}Éand“con•¸ãv“enien“t–}Édevices“for“tš¸ãypGesetting“mathematical“form˜ulas.‘ë#Seen“inŽ¡‘'¿¬this–ƒ4ligh¸ãt,‘άautomatic“program“formatting“is“only“a“simple“instance“of“automaticŽ¡‘'¿¬tš¸ãypGesetting–é[55Ž‘ ,‘Np.“652].‘ -So“prett˜yprin˜ting“algorithms“that“rely“on“professionalŽ¡‘'¿¬t¸ãypšGesetters–hcan“b˜e“simpler“and“pro˜duce“b˜etter“results“at“the“same“time,‘—ˆb˜ecause“a“lotŽ¡‘'¿¬of–¥the“formatting“problems“(e.g.“alignmenš¸ãt,–ÈIline-breaking,“t˜ypGesetting‘¥mathematicalŽ¡‘'¿¬formš¸ãulas)–UUcan“bGe“tak˜en“on“b˜y“the“t˜ypGesetter.Ž¡‘6¿¬In–|õthis“cš¸ãhapter“deals“with“the“general“issue“of“prett˜yprin˜ting.‘è¦It“places“a“widerŽ¡‘'¿¬view–UUon“the“ eld“and“tries“to“loGcate“the“Pretzel“system“within“the“latest“researc¸ãh.ŽŸ Qã‘'¿¬Ì5.1Ž‘L¦Prett•ŒÌyprin“ting–ffwith“F‘þ¦format“CommandsŽŸç‘@¿®²\W‘ÿ*ªell,–ÿÖI›êZm¸ãust‘êvconfess,“I˜w•¸ãas›êvv“ery˜close˜to˜thro“wing˜the˜whole˜ÈCWEB‘êZ²a“w“a“yŽŽŸK’×lx39ŽŽŒ‹(ß ½\È ýN£8‘63ײ40’©ÛÃCHAPTER–UU5.‘ÇON“PRETTYPRINTINGŽŽ ˜G ý„‘O3Ù²and––switcš¸ãhing“to“something“without“an˜y“prett˜yprin˜ting,‘Kælik˜e“Ènuweb“²orޤ ‘O3ÙÈnoweb².‘–ÌI›aginstalled–a¬Ènuweb²,‘¤Ârewrote“the“ÈMatrix2D˜²example“in¸ãto“it,‘¤ÂranŽ¡‘O3Ùit–µïthrough“and“{“returned“bacš¸ãk“to“ÈCWEB².“I‘µÖprobably“got“spGoiled“b˜y“theŽ¡‘O3Ùnice-lošGoking–UUoutput“it“pro˜duces“{“almost“alw•¸ãa“ys."Ž©P2‘O3ÙJan–UUDv¸ãorak“[12Ž‘ ]ŽŸû‘63×The› prett•¸ãyprin“ting˜methoGd˜used˜b“y˜Pretzel˜can˜bGe˜called˜Îpr‘ÿ}'ettyprinting–i.e.“an“inputŽ¡‘63× le–Pzis“prošGcessed“and“translated“in¸ãto“an“output“ le“according“to“sp˜ecial“rules.‘p)Here,Ž¡‘63×the–Šinput“ le“is“the“patc¸ãh“of“source“cošGde“that“shall“b˜e“prett•¸ãyprin“ted–Šand“the“outputŽ¡‘63× le–Hûis“the“text“suited“for“the“tš¸ãypGesetter.‘m©The“translation“rules“represen˜t“the“spGecialŽ¡‘63×w•¸ãa“y–UUin“whic¸ãh“source“cošGde“should“b˜e“formatted.Ž¡‘E3×The––Šmain“assumption“is“that“wš¸ãe“ha˜v˜e“a“text“formatter“that“uses“Îc–ÿ}'ontr“ol‘»jse-Ž¡‘63×quenc‘ÿ}'es‘IJ(or–ò|Îtags‘Ò!²)“inside“the“actual“text“b•Go“dy–ò|for“spGecifying“all“the“di erenš¸ãt“w˜a˜ysŽ¡‘63×of–0œformatting“(sucš¸ãh“as“fon˜ts,–7õinden˜tation,“spacing,“etc.).‘eŠAnother–0œterm“for“this“w˜a˜yŽ¡‘63×of–Hformatting“con¸ãtrol“is“Îin-text›Yæpr–ÿ}'o“c“e“dur“al˜markup‘·à²and–Hsystems“using“this“tec¸ãhniqueŽ¡‘63×are–wÑcommonly“called“Îdo–ÿ}'cument‘³ c“ompilers–wѲ(though“this“mighš¸ãt“only“refer“to“the“w˜a˜yŽ¡‘63×they–^:w¸ãork,‘`snot“to“viewing“text“proGcessing“as“programming).‘ŒvCommon“examples“ofŽ¡‘63×suc•¸ãh›÷t“yp•Gesetting˜systems˜are˜T‘þU>Ÿ'EŽ‘ãxX˜and˜the˜ÇUNIX˜²to“ols˜Nro /T‘ÿ*ªro .‘ÕñDuring˜theŽ¡‘63×prošGcessing–Îof“the“input“the“only“thing“it“do˜es“is“to“enric¸ãh“the“stream“of“incomingŽ¡‘63×information–Dîwith“spGecial“con¸ãtrol“sequences“that“I‘Dêcall“Îformat‘„Ðc‘ÿ}'ommands“²(or“ÎformatŽ¡‘63×c‘ÿ}'ommand‘ªwprimitives²).‘»YThese–mÛcommands“are“tags“that“are“left“for“the“t¸ãypGesetter“toŽ¡‘63×inš¸ãterpret.‘µrThe–Á9set“of“format“commands“used“b˜y“Pretzel“is“basically“the“initial“setŽ¡‘63×used–Ûbš¸ãy“Kn˜uth.‘óT‘ÿ*ªo“understand“this“proGcedure,‘ü|see“c˜hapter“2.‘óThe“original“doGcu-Ž¡‘63×men•¸ãts›cÞb“y˜Kn“uth˜[29Ž‘ ]˜and˜Kn“uth˜and˜Levy˜[33Ž‘ ]˜presen“t˜the˜algorithm˜in˜(in)formalŽ¡‘63×detail.ŽŸ zb‘63×Ì5.2Ž‘[:A–ffShort“History“of“Prett•ŒÌyprin“tingŽŸç‘O3Ù²\Nevš¸ãertheless–ƒ4I‘‚ÿstrongly“disagree“with“pGeople“sa˜ying“that“prett˜y-prin˜tingŽ¡‘O3Ùis– Ánot“wš¸ãorth“the“e ort“for“an˜y˜one“in“general;‘†wthis“depGends“v˜ery“m˜uc˜hŽ¡‘O3Ùon–4‹ones“particular“situation“and“purpGose.‘fÙIn“some“cases“prett•¸ãy-prin“tingŽ¡‘O3Ùma•¸ãy›UUev“en˜bGe˜the˜main˜reason˜to˜opt˜for˜literate˜programming."ަ‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[61Ž‘ ]ŽŸû‘63×In–ßIthis“section“I‘ß+will“givš¸ãe“a“brief“c˜hronological“o˜v˜erview“o˜v˜er“the“area“of“prett˜yprin˜t-Ž¡‘63×ing,–UUtry“to“structure“the“ eld,“and“will“shoš¸ãw,“ho˜w“the“presen˜t“system“ ts“in˜to“it.ŽŸfÔ‘63×Í5.2.1Ž‘_s×Historical‘€NotesŽŸuT‘63ײThe›èÊprett•¸ãyprin“ting˜of˜coGde˜has˜a˜long˜tradition˜that˜not˜only˜originates˜from˜theŽ¡‘63×compulsion–s/to“tš¸ãypGeset“programs“for“publication.‘ËVThe“readabilit˜y“or“ev˜en“the“sheerŽ¡‘63×bGeautš¸ãy–¬of“a“prett˜yprin˜ted“algorithm“ha˜v˜e“also“bGeen“a“k˜ey“motiv‘ÿqÇation“to“this“part“ofŽ¡‘63×computer‘UUscience.Ž¡‘E3×The–1‡ rst“pšGeople“to“call“sp˜ecial“attenš¸ãtion“to“formatting“issues“w˜ere“probably“P˜e-Ž¡‘63×ter–GvNaur,›J‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»This–this“methoGd“to“ÇP‘ÿ ascal².Ÿü^ÿ±3ŽŽ‘–Þ²The“fact“that“rules“for“la•¸ãy“out–O>and“grammar“are“oftenŽ¡‘63×closely–\¼related“[36Ž‘ ]“also“is“a“strong“indication“that“this“methoGd“is“in“fact“adequate.Ž¡‘63×The–‚¶trend“to•¸ãw“ards–‚¶formal“spšGeci cation“in“this“area“has“indeed“b˜een“\v¸ãery“fortunate"Ž¡‘63×[68Ž‘ ]– Žand“has“also“pro•¸ãv“ed– Žto“bGe“useful“in“other“areas,‘+sucš¸ãh“as“syn˜tax-directed“editorsŽ¡‘63×[56Ž‘ ].Ž© E3×T›ÿ*ªo–0tthis“end“Rose“and“W˜elsh“[55Ž‘ ]“ha•¸ãv“e›0tadv“oGcated˜the˜in“tegration˜of˜format˜rulesŽ¡‘63×within–ñMthe“language“synš¸ãtax“on“the“language“design“lev˜el.‘PoThey“state“that“\programŽ¡‘63×format–ú‡decisions“[should“bGe“put]“in“the“domain“of“the“language's“designer,‘#ÓratherŽ¡‘63×than–»1its“sevš¸ãeral“implemen˜tators“or“n˜umerous“users,‘Úwhic˜h“implies“uniformly“format-Ž¡‘63×ted– programs“of“impro•¸ãv“ed› readabilit“y˜and˜therefore˜usabilit“y‘ÿ*ª."‘‘K[55Ž‘ ,‘7Ìp.˜651]˜TheirŽ¡‘63×idea–üôdošGes“Înot“²try“to“imp˜ose“rigid“formatting“rules“on“users“of“existing“or“future“lan-Ž¡‘63×guages.‘¦wInstead–¼:they“propGose“a“metasyn¸ãtax“and“a“set“of“guidelines“that“constrainŽ¡‘63×and–kdirect“the“language“designer“in“the“placing“of“format“commands.‘ZyThese“formatŽ¡‘63×commands–—Ùinclude“commands“for“indenš¸ãtation,‘½¿as“w˜ell“as“for“line“breaks“and“optionalŽ¡‘63×line–Ùbreaks“(so“called“\fold“options").‘4žThe“metasyn¸ãtax“and“the“guidelines“only“e ectŽ¡‘63×rather–»nglobal“issues“of“formatting“but“ensure“consistency“across“language“bGorders.Ž¡‘63×They–F0also“presenš¸ãt“a“folding“algorithm“that“implemen˜ts“the“format“commands“fromŽ¡‘63×their‘UUlist.ަ‘E3×This–Xtlast“approacš¸ãh“b˜y“Rose“and“W‘ÿ*ªelsh“is“curren˜tly“the“`state“of“the“art'“in“pro-Ž¡‘63×gram›•la•¸ãy“out˜issues.‘1W‘ÿ*ªo•Go“dman˜has˜published˜a˜thorough˜discussion˜of˜this˜sc¸ãhemeŽ¡‘63×and–`Ahas“propGosed“re nemenš¸ãts“[68Ž‘ ]“that“ho˜w˜ev˜er“do“not“alter“the“main“pGoin˜ts.‘’ŒIt“isŽ¡‘63×an–AOapproacš¸ãh“that“in“some“w˜a˜y“surpasses“the“area“of“prett˜yprin˜ting“in“that“it“forcesŽ¡‘63×the–NÙformatting“grammar“to“bGe“equal“to“the“language“reference“grammar.‘ožHo•¸ãw“ev“er,Ž¡‘63×Kn•¸ãuth›“usho“ws˜that˜a˜prettprin“ting˜grammar˜can˜bGe˜m“uc“h˜simpler˜than˜a˜full-size˜lan-Ž¡‘63×guage–kÒgrammar,‘qqbGecause“it“is“able“to“treat“semanš¸ãtically“di eren˜t“con˜tructs“equallyŽ¡‘63×as–UUthey“are“formatted“in“the“same“w•¸ãa“y–UU(e.g.“ÆifŽ‘ ¨²,“ÆforŽ‘ª¦²and“ÆwhileŽ‘!L²statemen¸ãts).Ž‘63ן  …‰ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»It–gis“inšÃŽteresting“that“Mateti's“solution“w˜as“the“result“of“formalization“(due“to“v˜eri cation“needs)ŽŸ €and–ÕXthat“Oppšthe“ÈWEB“²system“shoš¸ãws,‘BºT‘þU>Ÿ'EŽ‘ãxX“has“bGeen“used“as“a“bac˜k“end“for“a“prett˜yprin˜ter,Ž¡‘'¿¬but–Ó2it“has“remained“the“only“one“that“I‘Óam“a•¸ãw“are–Ó2of.‘ë_This“leads“to“the“question,Ž¡‘'¿¬whš¸ãy–ü™so“little“prett˜yprin˜ters“faciliate“t˜ypGesetters“as“bac˜k“ends“for“their“output?‘T3ThisŽ¡‘'¿¬question–é is“vš¸ãery“striking,‘þ³as“t˜ypšGesetters“o er“p˜o•¸ãw“erful–é capabilities,‘þ³and“for“example,Ž¡‘'¿¬T‘þU>Ÿ'EŽ‘ãxX's–è¥line“breaking“algorithm“has“bšGeen“adv¸ão˜cated“to“b˜e“v¸ãery“suitable“for“exactlyŽ¡‘'¿¬this–UUtask“[28Ž‘ ].ŽŸ ´Ò‘6¿¬OppGen–UUgivš¸ães“an“answ˜er“to“this“in“his“papGer:ަ‘@¿®\Ho•¸ãw“ev“er,‘Šit–L·[the“algorithm]“seems“to“strik¸ãe“a“reasonable“balance“bGe-Ž¡‘@¿®t•¸ãw“een–ô„sophistication“and“simplicit¸ãy‘ÿ*ª,‘áand“to“bšGe“appropriate“as“a“sub˜com-Ž¡‘@¿®pGonenš¸ãt–UUof“editors“and“the“lik˜e."‘qÇ[44Ž‘ ,“p.“466]ަ‘'¿¬It– µis“surely“the“question“whether“yš¸ãou“are“prett˜yprin˜ting“on“screen“or“preparing“aŽ¡‘'¿¬publication.‘.¼But–”Qthe“other“part“of“the“answš¸ãer“is“ma˜ybGe“not“so“ob˜vious“and“has“toŽ¡‘'¿¬do–UUwith“the“traditional“fears“in“the“programming“comm•¸ãunit“y‘ÿ*ª.Ž© ´Ò‘6¿¬A‘Q†lot–Q‡of“prett•¸ãyprin“ters›Q‡ha“v“e˜bGeen˜built˜as˜parts˜of˜larger˜programming˜en“viron-Ž¡‘'¿¬menš¸ãts–.and“w˜ere“constituen˜t“parts“of“this“larger“system.‘WeA‘lac˜k“of“moGdularit˜y“in“theŽ¡‘'¿¬design–Vÿ(as“for“example“the“fundamenš¸ãtal“distinction“presen˜ted“in“these“sections“andŽ¡‘'¿¬visialized–V¾in“ gure“5.1)“often“makš¸ães“the“resuing“of“sub•Gcomp“onen˜ts‘V¾imp“ossible.‘vTheŽ¡‘'¿¬prett•¸ãyprin“ters–UUhide“somewhere“in“the“larger“system“and“are“dicult“to“extract.ަ‘6¿¬Another–ÕpGoinš¸ãt“is“that“an“old“habit“of“programmers“is“their“striv˜e“for“indepGen-Ž¡‘'¿¬dence.›¯They–iÂdo“not“w•¸ãan“t–iÂtheir“systems“to“rely“on“other“systems.˜But“this“habit“isŽ¡‘'¿¬hopšGefully–UUgetting“less“frequen¸ãt“to˜da¸ãy‘ÿ*ª.ŽŸ½Ž‘'¿¬Í5.2.4Ž‘Pÿ¬The–€Set“of“F‘þàormat“CommandsŽŸÅÙ‘'¿¬²The–Eáformat“commands“passed“bGet•¸ãw“een–Eáthe“fronš¸ãt“end“and“the“bac˜k“end“of“the“pret-Ž¡‘'¿¬t•¸ãyprin“ter–›ªare“the“only“means“to“con•¸ãv“ey–›ªthe“formatting“pGolicy“to“the“actual“formatterŽ¡‘'¿¬(see–™. gure“5.1“that“visualizes“the“moGdularitš¸ãy“of“a“prett˜yprin˜ter).‘=RThis“means“thatŽ¡‘'¿¬ev•¸ãery›dkt“ypGesetting˜feature˜m“ust˜bGe˜expressible˜in˜them.‘ŸIn˜conjunction˜with˜thisŽ¡‘'¿¬wš¸ãork–O¢it“is“impGortan˜t“to“ask,‘Ž5if“the“command“set“pro˜vided“in“the“curren˜t“PretzelŽ¡‘'¿¬system–Þfis“sucienš¸ãt“to“format“ev˜ery“desired“feature“that“w˜e“can“pGossibly“think“of.Ž¡‘'¿¬The–5answš¸ãer“is“clearly“`No!',‘oas“there“still“are“opGen“prett˜yprin˜ting“problems.‘V¼W‘ÿ*ªe“willŽ¡‘'¿¬ha•¸ãv“e–UUa“loGok“at“them“later.‘qÇBut“just“hoš¸ãw“sucien˜t“is“the“command“set?ަ‘6¿¬First–¸wš¸ãe'll“loGok“at“whether“it“allo˜ws“full“con˜trol“o˜v˜er“line“breaks“and“inden˜tation.Ž¡‘'¿¬A‘ÈPdetailed–Èncomparison“shoš¸ãws“that“the“command“set“used“b˜y“Rose“and“W‘ÿ*ªelsh“is“aŽŽŽŒ‹,Z_ ½\È ýN£8‘63ײ44’©ÛÃCHAPTER–UU5.‘ÇON“PRETTYPRINTINGŽŽ ˜G þ3¬ŸÞ9Ÿ¾ù‘u Îand–“çformat“c‘ÿ}'ommandsŽŽŽŽ’æÐ5ŸˆûÞ„fd#9‘ÜÆížÌÎóäO£ line10¬ŽŽ’é…ÔŸâe]„fd ƒt‘öžÌÎ-ŽŽ‘Yë韼v«„fdÞóŽ‘a©¯Ÿ¼v«„fdÞóŽ‘iguŸ¼v«„fdÞóŽ‘q%;Ÿ¼v«„fdÞóŽ’ÖŽ{Ÿ¼v«„fd¬QŽ’ÝæöŸ¼v«„fd¬QŽ’å?qŸ¼v«„fd¬QŽ’ì—쟼v«„fd¬QŽ’óðgŸ¼v«„fd¬QŽ’ûH⟼v«„fd¬QŽ’¡]Ÿ¼v«„fd¬QŽ’ ùØŸ¼v«„fd¬QŽ’RSŸ¼v«„fd¬QŽ’ªÎŸ¼v«„fd¬QŽ’ IŸ¼v«„fd¬QŽ’'[ÄŸ¼v«„fd¬QŽ’.´?Ÿ¼v«„fd¬QŽ’6 ºŸ¼v«„fd¬QŽ’=e5Ÿ¼v«„fd¬QŽ’D½°Ÿ¼v«„fd¬QŽ’L+Ÿ¼v«„fd¬QŽ’Sn¦Ÿ¼v«„fd¬QŽ’ZÇ!Ÿ¼v«„fd¬QŽ’bœŸ¼v«„fd¬QŽ’ixŸ¼v«„fd¬QŽ’pÐ’Ÿ¼v«„fd¬QŽ’x) Ÿ¼v«„fd¬QŽ’¥–Ÿ®·^„AºfeŽŽ’¥–ŸÔ¦„÷YfeŽ’¥ÉMŸÔ¦?ŽŽ‘gŸŸÔ¦‰fe}o\ŸÍÕ„ÍÕfeŸñŽ‘|¢’„ÍÕfeŽžfe‰fe}o\ŽŽŽŸ¶Ø;’^´Îstr–ÿ}'e“am–“çof“stringsŽŽŽŽ‘gŸ ÿ}ò0‰fe}o\ŸÍÕ„ÍÕfeŸñŽ‘|¢’„ÍÕfeŽžfe‰fe}o\ŽŽŽŸçi‘wÉD²formatting‘UUalgorithmŽŽŽŽžôO‘^b6ó†›Zcmr5°.ŽŽŽžôO‘cÍt.ŽŽŽžôO‘i8².ŽŽŽžôO‘n£ð.ŽŽŽžôO‘t..ŽŽŽžôO‘yzl.ŽŽŽžôO‘~åª.ŽŽŽžôO’„Pè.ŽŽŽžôO’‰¼&.ŽŽŽžôO’'d.ŽŽŽžôO’”’¢.ŽŽŽžôO’™ýà.ŽŽŽžôO’Ÿi.ŽŽŽžôO’¤Ô\.ŽŽŽžôO’ª?š.ŽŽŽžôO’¯ªØ.ŽŽŽžôO’µ.ŽŽŽžôO’ºT.ŽŽŽžôO’¿ì’.ŽŽŽžôO’ÅWÐ.ŽŽŽžôO’ÊÃ.ŽŽŽžôO’Ð.L.ŽŽŽžôO’Õ™Š.ŽŽŽžôO’ÛÈ.ŽŽŽžôO’àp.ŽŽŽžôO’åÛD.ŽŽŽžôO’ëF‚.ŽŽŽ ÿs‘^b6.ŽŽŽ ÿs‘cÍt.ŽŽŽ ÿs‘i8².ŽŽŽ ÿs‘n£ð.ŽŽŽ ÿs‘t..ŽŽŽ ÿs‘yzl.ŽŽŽ ÿs‘~åª.ŽŽŽ ÿs’„Pè.ŽŽŽ ÿs’‰¼&.ŽŽŽ ÿs’'d.ŽŽŽ ÿs’”’¢.ŽŽŽ ÿs’™ýà.ŽŽŽ ÿs’Ÿi.ŽŽŽ ÿs’¤Ô\.ŽŽŽ ÿs’ª?š.ŽŽŽ ÿs’¯ªØ.ŽŽŽ ÿs’µ.ŽŽŽ ÿs’ºT.ŽŽŽ ÿs’¿ì’.ŽŽŽ ÿs’ÅWÐ.ŽŽŽ ÿs’ÊÃ.ŽŽŽ ÿs’Ð.L.ŽŽŽ ÿs’Õ™Š.ŽŽŽ ÿs’ÛÈ.ŽŽŽ ÿs’àp.ŽŽŽ ÿs’åÛD.ŽŽŽ ÿs’ëF‚.ŽŽŽžôO‘^b6.ŽŽŽŸú‰‘^b6.ŽŽŽŸõÓ‘^b6.ŽŽŽŸï²•‘^b6.ŽŽŽŸêGW‘^b6.ŽŽŽŸäÜ‘^b6.ŽŽŽŸßpÛ‘^b6.ŽŽŽŸÚ‘^b6.ŽŽŽŸÔš_‘^b6.ŽŽŽŸÏ/!‘^b6.ŽŽŽŸÉÃã‘^b6.ŽŽŽŸÄX¥‘^b6.ŽŽŽŸ¾íg‘^b6.ŽŽŽŸ¹‚)‘^b6.ŽŽŽŸ´ë‘^b6.ŽŽŽŸ®«­‘^b6.ŽŽŽŸ©@o‘^b6.ŽŽŽŸ£Õ1‘^b6.ŽŽŽŸžió‘^b6.ŽŽŽŸ˜þµ‘^b6.ŽŽŽŸ““w‘^b6.ŽŽŽŸŽ(9‘^b6.ŽŽŽŸˆ¼û‘^b6.ŽŽŽŸƒQ½‘^b6.ŽŽŽ ÿ}æ‘^b6.ŽŽŽ ÿx{A‘^b6.ŽŽŽ ÿs‘^b6.ŽŽŽžôO’ëF‚.ŽŽŽŸú‰’ëF‚.ŽŽŽŸõÓ’ëF‚.ŽŽŽŸï²•’ëF‚.ŽŽŽŸêGW’ëF‚.ŽŽŽŸäÜ’ëF‚.ŽŽŽŸßpÛ’ëF‚.ŽŽŽŸÚ’ëF‚.ŽŽŽŸÔš_’ëF‚.ŽŽŽŸÏ/!’ëF‚.ŽŽŽŸÉÃã’ëF‚.ŽŽŽŸÄX¥’ëF‚.ŽŽŽŸ¾íg’ëF‚.ŽŽŽŸ¹‚)’ëF‚.ŽŽŽŸ´ë’ëF‚.ŽŽŽŸ®«­’ëF‚.ŽŽŽŸ©@o’ëF‚.ŽŽŽŸ£Õ1’ëF‚.ŽŽŽŸžió’ëF‚.ŽŽŽŸ˜þµ’ëF‚.ŽŽŽŸ““w’ëF‚.ŽŽŽŸŽ(9’ëF‚.ŽŽŽŸˆ¼û’ëF‚.ŽŽŽŸƒQ½’ëF‚.ŽŽŽ ÿ}æ’ëF‚.ŽŽŽ ÿx{A’ëF‚.ŽŽŽ ÿs’ëF‚.ŽŽŽŸäçÊ’t†²tš¸ãyp•Geset‘UUdo“cumen˜tŽŽŽŽŸ‹~K’t†unformatted–UUsource“coGdeŽŽŽŽ ÿpf‘gxprett•¸ãyprin“terŽŽŽŽŸ¶Ø;’ùÎ0language–UUdepGendenš¸ãt“fron˜t“endŽŽŽŽŸÇõ’òœhlanguage–UUindepGendenš¸ãt“bac˜k“endŽŽŽŽŸˆÈ¬’‹Pfparser‘UUusingŽŽŽŽŸ“Ÿ(‘q¥¶prett•¸ãyprin“ting‘UUgrammarŽŽŽŽŽŽŽŽŸ ‘i ”Figure–UU5.1:‘qÇThe“mošGdule“structure“of“mo˜dern“prett•¸ãyprin“tersŽŽŽŸo1‘63×subset–K of“Kn¸ãuth's“command“set“(ÎindentŽ‘Jú²,‘ˆvÎoutdentŽ‘%ïß²,‘ˆvÎfor–ÿ}'c“eŽ‘ÛB²,‘ˆvÎbr–ÿ}'e“aksp“ac“eŽ‘1àå²,‘ˆvÎoptŽ‘©²).Ÿü^ÿ±4ŽŽ‘ ÏV²Roseޤ ‘63×and–tÅW‘ÿ*ªelsh“in“fact“shoš¸ãw“b˜y“example,‘| that“an˜y“language“syn˜tax“can“bGe“transformedŽ¡‘63×inš¸ãto–$Üa“formatted“syn˜tax“that“in“itself“is“capable“of“spGecifying“all“desirable“folds“andŽ¡‘63×cš¸ãhanges–nTof“inden˜tation.‘¼ÃThe“main“precondition“for“this“transformation“is,‘t“that“theŽ¡‘63×starting–~šgrammar“is“conš¸ãtext“free.‘*4None“of“the“ v˜e“basic“commands“is“supGer uous“(asŽ¡‘63×w•¸ãe›M%ha“v“e˜seen˜in˜the˜ rst˜part˜of˜this˜c“hapter)˜so˜w“e˜can˜call˜these˜basic˜commandsŽ¡‘63×the‘UUÎne–ÿ}'c“essary›“çc“ommand˜set‘òز.Ž¡‘E3×The–Ònecessary“command“set“enables“the“ rst“pGoin¸ãt“of“the“basic“actions“of“a“pret-Ž¡‘63×t•¸ãyprin“ter›~Ämen“tioned˜on˜page˜41.‘îThe˜other˜t“w“o˜pGoin“ts˜(additional˜loGcal˜spacing˜ofŽ¡‘63×synš¸ãtactic–•aconstructs;‘µgusing“di eren˜t“fon˜ts)“are“things“that“depGend“on“the“capabili-Ž¡‘63×ties–£Ôof“the“tš¸ãypGesetter“and“are“not“so“m˜uc˜h“a“question“of“the“format“command“set.Ž¡‘63×Thanks–tto“proGcedural“markup,‘¡%as“long“as“the“prett•¸ãyprin“ter›tallo“ws˜us˜to˜insert˜stringsŽ¡‘63×bGet•¸ãw“een›Lšan“y˜t“w“o˜tok“ens˜at˜lexical˜lev“el˜w“e˜are˜able˜to˜handle˜these˜t“w“o˜pGoin“ts˜toGo.Ž¡‘63×Ho•¸ãw“ev“er,‘"öin–^Rubin's“rather“assemš¸ãbler“lik˜e“command“set“[56Ž‘ ,‘"öp.“122]“w˜e“see“that“theŽ¡‘63×necessary–Šcommand“set“still“lacš¸ãks“full“con˜trol“o˜v˜er“v˜ertical“and“horizon˜tal“spacing.Ž¡‘63×One–±“can“argue“o•¸ãv“er–±“what“parts“of“this“issue“bGelong“inš¸ãto“the“domain“of“the“t˜ypGesetterŽ¡‘63×and–Ëwhat“should“bGe“left“to“the“user's“conš¸ãtrol,‘èŽbut“there“surely“is“an“ob˜vious“needŽ¡‘63×to–p‹express“additional“v¸ãertical“separation“in“terms“of“a“simple“format“command.‘ÃjInŽ¡‘63×our–UUcase“this“is“the“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘+ïDzcommand.Ž¡‘E3×The–úZother“command“that“givš¸ães“bGetter“con˜trol“o˜v˜er“horizon˜tal“space“is“Îb‘ÿ}'ackupŽ‘!|š².Ž¡‘63×Both‘ \Îb‘ÿ}'ackupŽ‘%œø²and‘ \Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘-_Õ²can– \bGe“simš¸ãulated“b˜y“sequences“of“commands“from“theŽ¡‘63×necessary–5ùcommand“set.Ÿü^ÿ±5ŽŽ‘ %²So“they“are“not“necessary“but“con•¸ãv“enien“t‘5ùshort-hands.Ž‘63ןʼnff‰¬Ÿ J=‘ "5Ÿý-:¼4ŽŽŽ‘LÜ»The–Z$commands“used“bšÃŽy“Rose“and“W‘ÿJªelsh“are“denoted“b˜y“the“spæsymÃŽb‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»The–#‹sequence“`Ôfor•¥c“eŽ‘Cï»,‘7Ôb¥ackupŽ‘€·»'“is“equal“to“`ÔoutdentŽ‘žö»,‘7Ôfor•¥c“eŽ‘{»,‘7ÔindentŽ‘r~»'“and“`Ôbig‘†Ò‰ff¢$Ž‘(öfor•¥c“eŽ‘õp»'“is“somethingŽŽŽŒ‹-l  ½\È ýN£8‘'¿¬Ã5.2.‘ÇA–UUSHOR›ÿ*ªT“HISTOR˜Y“OF“PRETTYPRINTING‘v9€²45ŽŽ ˜G ý±ãŽŸÜœrŸóæd‘1  necessary–UUcommand“set“µN‘ Þ4²=Ž’ÄÇ-¸f‘UUÎindentŽ‘ O²,‘UUÎoutdentŽ‘$¼¾²,‘UUÎfor–ÿ}'c“eŽ‘¨!²,‘UUÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘4[ײ,‘UUÎoptŽ‘(ݸgŽŽ¤ ‘-¿¬²con•¸ãv“enien“t–UUcommand“set“µC‘ ~5²=Ž’ÄÇ-µN‘lp¸[–UUf“Îb‘ÿ}'ackupŽ‘ ו²,“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘+ïǸgŽŽ¡‘6Xì²sucien¸ãt–UUcommand“set“µS‘ Z¦²=Ž’ÄÇ-µC‘ q¸[–UUf“Îc–ÿ}'anc“elŽ‘ná²,“Îno‘‰ffŽ‘®indentŽ‘1_o¸gŽŽŽŽŽŸ!qÇ‘lHܲFigure–UU5.2:‘qÇNaming“of“subsets“of“the“command“set.ŽŽŽŸt‘'¿¬W‘ÿ*ªe–awill“call“them,‘’together“with“the“basic“commands“the“Îc–ÿ}'onvenient›R¡c“ommand˜set‘òز.Ž© :‘6¿¬T¸ãypšGesetting–Nlines“of“co˜de“ ushleft“is“not“a“feature“commonly“needed“in“mo˜dernޤ ‘'¿¬structured–÷âprogramming“languages,‘`„except“in“ÇC²/ÇCŸÿ²++Ž‘†when“using“preproGcessorŽ¡‘'¿¬directiv¸ães–”Ù(and“still“they“do“not“bGelong“to“the“actual“language“itself‘Ç).‘1žThe“Îno‘‰ffŽ‘®indentŽŽ¡‘'¿¬²command–Ü‹caters“for“them“but“it“is“hardly“necessary“in“other“languages,‘ô³where“aloneŽ¡‘'¿¬the–©ãidea“of“excluding“single“lines“from“the“o•¸ãv“erall›©ãinden“tation˜frame˜violates˜all˜rulesŽ¡‘'¿¬of›UUgo•Go“d˜program˜la•¸ãy“out.ަ‘6¿¬Finally–úthe“Îc–ÿ}'anc“elŽ‘% ®²command“doGes“not“add“an¸ãy“striking“new“features“to“theŽ¡‘'¿¬command–Y°set.‘~ØIt“just“alloš¸ãws“more“ exibilit˜y“in“the“placemen˜t“of“format“commandsŽ¡‘'¿¬in–€âthe“output.‘ôoA‘€×wš¸ãell“placed“Îc–ÿ}'anc“elŽ‘"P²command“can“obliterate“a“dozen“rules“of“y˜ourŽ¡‘'¿¬prett•¸ãyprin“ting–‘ grammar“and“thš¸ãus“can“de ate“prett˜yprin˜ting“grammars“v˜ery“m˜uc˜h.Ž¡‘'¿¬So–È£if“yš¸ãou“de ne“suciency“as“incorpGorating“con˜v˜enience“and“ exibilit˜y“w˜e“could“callŽ¡‘'¿¬this–WFwhole“set“of“presenš¸ãted“commands“a“Îsucient–5c‘ÿ}'ommand“set².‘w™This,‘—Áho˜w˜ev˜er,Ž¡‘'¿¬naturally–Çmexcludes“the“opGen“problems“menš¸ãtioned“in“the“next“subsection.‘ÈThe“t˜w˜oŽ¡‘'¿¬subsets–UUof“this“sucien¸ãt“command“set“are“summarized“in“table“5.2.ŽŸI°‘'¿¬Í5.2.5Ž‘Pÿ¬Op`en›€Prett• yprin“ting˜ProblemsŽŸΑ@¿®²\No–ÒÚthere“isn't,‘2;and“there“w¸ãon't“bšGe“[a“metho˜d“of“v¸ãertically“aligningŽ¡‘@¿®statemenš¸ãts–ü×in“ÈCWEB²].“It“is“true“thatÈCWEB‘üÁ²forgets“y˜our“alignmen˜t,‘Šbut“y˜ouŽ¡‘@¿®should–Ç\realise“that“it“also“forgets“Îany“²la•¸ãy“out–Ç\feature“presenš¸ãt“in“y˜ourŽ¡‘@¿®source–Ææ le“(e.g.,‘#Jline“breaks).‘Æ{Apart“from“the“fact“that“it“w¸ãould“bGeŽ¡‘@¿®vš¸ãery–G“hard“to“in˜tegrate“an˜y“alignmen˜t“proGcessing“in˜to“ÈCWEAVE²'s“ordinaryŽ¡‘@¿®parsing–ê@opšGerations,‘zit“is“an“imp˜ossible“task“for“ÈCWEAVE²,“since“it“kno¸ãwsŽ¡‘@¿®nothing– AabGout“the“actual“width“of“iden¸ãti ers“and“other“items.‘“‹So“theŽ¡‘@¿®only–¤µpGossibilitš¸ãy“w˜ould“bGe“to“transmit“alignmen˜t“instructions“to“T‘þU>Ÿ'EŽ‘ãxX,‘ÈbutŽ¡‘@¿®T‘þU>Ÿ'EŽ‘ãxX–‹›t¸ãypšGesets“co˜de“in“paragraph“mo˜de“(breaking“lines“to“the“width“of“theŽ¡‘@¿®page–#§if“necessary),‘-—and“there“is“no“w•¸ãa“y–#§to“mix“that“with“an“alignmen¸ãt."ŽŸt‘@¿®Marc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[63Ž‘ ]ŽŸ8è‘'¿¬If–4³yš¸ãou“ha˜v˜e“ev˜er“tried“to“use“a“prett˜yprin˜ter“for“y˜our“o˜wn“coGde“y˜ou“will“surely“ha˜v˜eŽ¡‘'¿¬come–UUacross“problems“concerning“user“con•¸ãtrol.‘qÇY‘ÿ*ªeh“udai–UUstates,“thatŽ©*®‘@¿®\[.–ªª.“.“]‘¼“it–nDis“not“clear“that“anš¸ãy“automated“inden˜tation“sc˜heme“will“bGeŽ¡‘@¿®adequate,‘hŸas–dÃI‘d¿maš¸ãy“c˜hoGose“di eren˜t“w˜a˜ys“to“la˜y“out“the“same“constructŽ¡‘@¿®in–UUdi erenš¸ãt“parts“of“m˜y“program."‘qÇ[69Ž‘ ,“p.“85]ަ‘'¿¬W‘ÿ*ªo•Go“dman–NOgivš¸ães“an“example“for“this“pGoin˜t“that“he“calls“\adaptiv˜e“com˜bs"“[68Ž‘ ,‘‚êp.“616],Ž¡‘'¿¬where–UUa“long“ÆifŽ‘ ¨²/ÆelsifŽ‘ þ²statemen¸ãt“in“MoGdula-2“is“cited“as:ŽŸ8è‘1¿­ÆifŽ‘;ÊUÎlongexpr‘ÿ}'ession1Ž’„¶ÆthenŽŽ¤ :‘;¿®Îlongstatement1ŽŽ¡‘1¿­ÆelsifŽ‘HÊ«Îexpr2Ž‘e(ÆthenŽ‘"Îstmt2ŽŽ¡‘1¿­ÆelsifŽ‘HÊ«Îlongexpr‘ÿ}'ession3Ž’‘ ÆthenŽŽ¡‘;¿®Îlongstatement3ŽŽ¡‘1¿­ÆelseŽŽ¡‘;¿®Îlongstatement4ŽŽ‘'¿¬Ÿ‘‰ff‰¬Ÿ @»likšÃŽe–ÕX`Ôfor•¥c“eŽ‘Cï»,“Ônulp[lŽ‘âß»,“Ôfor•¥c“eŽ‘G»',“depha˜v˜eŽ¡‘63×commen•¸ãt›êstatemen“ts"˜b“y˜Kaelbling˜[25Ž‘ ]˜and˜that˜b“y˜Grogono˜[17Ž‘ ]˜strongly˜argueŽ¡‘63×that– §at“last“commen¸ãts“should“bGe“treated“equally“as“parts“of“the“language,‘—not“as“anŽ¡‘63×add-on–²Rthat“is“forgotten“at“ rst“pGoin¸ãt“during“compilation.‘ˆ¿Grogono“brings“this“toŽ¡‘63×the–ß)pGoinš¸ãt“b˜y“stating“that“\Commen˜ts“are“second“class“citizens."‘C[17Ž‘ ,‘žp.“80]“TheyŽ¡‘63×are–Rmostly“allo•¸ãw“ed›Ran“ywhere˜in˜the˜source˜coGde˜and˜prett“yprin“ters˜who˜w“an“t˜toŽ¡‘63×preservš¸ãe–àthem“in“the“output“ha˜v˜e“sev˜ere“problems“doing“that“without“destro˜yingŽ¡‘63×the–÷Žprogram's“format,‘ ObšGecause“they“ha•¸ãv“e–÷Žto“b˜e“incorp˜orated“inš¸ãto“the“prett˜yprin˜tingŽ¡‘63×grammar.Ž¡‘E3×There›¤âha•¸ãv“e˜bGeen˜attempts˜to˜do˜this˜in˜a˜structured˜w“a“y‘ÿ*ª,‘È-i.e.˜to˜divide˜commen“tsŽ¡‘63×inš¸ãto–‚{classes“and“to“treat“eac˜h“class“di eren˜tly“[53Ž‘ ,“56Ž›‚},“13Ž˜,“54Ž˜].‘ù8Rose“and“W‘ÿ*ªelshŽ¡‘63×distinguish›ûobGet•¸ãw“een˜pre-˜and˜pGostcommen“ts˜and˜state˜that˜commen“ts˜m“ust˜mo“v“eŽ¡‘63×with–šºthe“synš¸ãtactic“elemen˜ts“that“they“refer“to“[55Ž‘ ,‘¬p.“660].‘AöKaelbling“ev˜en“goGes“asŽ¡‘63×far–k%as“to“demand“\scopGed“commenš¸ãts",‘p™i.e.“commen˜ts“that“explicitly“sho˜w“to“whic˜hŽ¡‘63×part–UUof“the“program“they“bGelong.Ž¡‘E3×All–lNthese“attempts“ha•¸ãv“e–lNthe“same“goal,‘r but“the“problem“of“prett•¸ãyprin“ting‘lNcom-Ž¡‘63×menš¸ãts–÷hwill“only“bGe“solv˜ed,‘íif“they“are“treated“as“an“equal“part“of“a“programmingŽ¡‘63×language–UUand“th¸ãus“are“included“in“the“reference“grammar.Ž‘63× €Cü‰ff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»W‘ÿJªo•Ÿ'EŽ‘ãxX“allo˜wsŽ¡‘@¿®selection–UUof“a“doGcumenš¸ãt“st˜yle“indepGenden˜tly“from“its“con˜ten˜ts)“[...]"ŽŸ""‘@¿®Marc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[62Ž‘ ]Ž©ª«‘'¿¬After–"§haš¸ãving“ nally“implemen˜ted“and“tested“the“Pretzel“program“I‘"rha˜v˜e“noticed,Ž¡‘'¿¬that–Îethe“program“doGesn't“do“vš¸ãery“m˜uc˜h“at“all,‘ì©although“it“suits“the“spGeci cationsŽ¡‘'¿¬that–nƒbšGelonged“to“this“pro‘Ž8ject.‘½RT‘ÿ*ªo“enjo¸ãy“b˜eautifully“formatted“source“co˜de“y¸ãou“stillŽ¡‘'¿¬ha•¸ãv“e– ’to“construct“yš¸ãour“prett˜yprin˜ting“grammar.‘5†As“is“seems,‘Ĺthe“w˜ork“of“ ne“tuningŽ¡‘'¿¬sucš¸ãh–¡a“grammar“that“the“prett˜yprin˜ter“is“able“to“handle“the“last“formatting“detailŽ¡‘'¿¬yš¸ãou–øàdesire“is“quite“tedious“and“time-consuming,‘ ^espGecially“if“y˜ou“start“to“build“y˜ourŽ¡‘'¿¬grammar–Uífrom“scratcš¸ãh.‘sBut“after“constructing“suc˜h“a“grammar“for“ÇP‘ÿ ascal“²andŽ¡‘'¿¬applying–S”it“to“a“few“ev•¸ãeryda“y-example–S”ÇP‘ÿ ascal“²source“coGdes,‘SîI‘S“wš¸ãas“astonished“ho˜wŽ¡‘'¿¬easy–y›it“wš¸ãas“to“c˜hange“the“loGoks“of“the“prett˜yprin˜ted“text.‘ÞšI‘yPthink“that“startingŽ¡‘'¿¬with–Låa“formal“grammar“of“yš¸ãour“fa˜v˜ourite“language“and“trying“to“enhance“it“andŽ¡‘'¿¬transform–]Nit“inš¸ãto“a“prett˜yprin˜ting“grammar“is“surely“a“bGetter“w˜a˜y“to“reac˜h“y˜ourŽ¡‘'¿¬goal.‘A’I‘š‡suppšGose–š™that“the“Pretzel“program“could“b˜e“the“righ¸ãt“to˜ol“to“help“y¸ãou“withŽ¡‘'¿¬this‘UUtask.Ž¡‘6¿¬Ho•¸ãw“ev“er,‘áÌsince–ŵonly“few“pšGeople“ha•¸ãv“e–ŵused“Pretzel“un¸ãtil“to˜da¸ãy“there“will“surelyŽ¡‘'¿¬bšGe–Ýma“lot“of“things“p˜eople“miss“when“using“the“program.‘IÏHere“are“a“few“things“I‘ÝOha•¸ãv“eŽ¡‘'¿¬though¸ãt–UUof“already:ަ‘'¿¬ÆAllo®9w›ÕTÈ/*Æ.–êª.“.“È*/˜Æcommen®9ts.ŽŽ’«#d²In–=Iplaces“where“the“user“has“an“empt¸ãy“proGduction“inŽ¡‘@¿®the–òformatted“grammar“ le“or“an“emptš¸ãy“tok˜en“de nition“in“the“formattedŽ¡‘@¿®tokš¸ãen–§| le“ le,‘üit“w˜ould“bGe“nice“to“ha˜v˜e“a“C‘§%lik˜e“commen˜ting“feature“withŽ¡‘@¿®opGening–Ûand“closing“delimiters.‘KYThe“`È//²'“commenš¸ãt“delimiter“isn't“nice“if“y˜ouŽ¡‘@¿®w•¸ãan“t–UUto“add“an“attribute“de nition“to“an“empt¸ãy“proGduction.Ž©DD‘'¿¬ÆCop•®9y‘ÕTcommen“ts.ŽŽ’€XͲIt– ³surely“wš¸ãould“mak˜e“the“generated“ ex“and“Bison“ les“moreŽ¡‘@¿®readable,‘ªUif–™UPretzel“wš¸ãould“cop˜y“the“commen˜ts“from“the“formatted“tok˜en“andŽ¡‘@¿®the–UUformatted“grammar“ les“in¸ãto“them.ަ‘'¿¬ÆGenerate–ÕTÈ%token“Æde nitions.ŽŽ’¹ϲIf–¥0one“w¸ãould“impGose“the“restriction“to“use“only“up-Ž¡‘@¿®pGercase–×^idenš¸ãti ers“as“terminal“tok˜en“names“Pretzel“could“automalically“gener-Ž¡‘@¿®ate–Åthe“list“of“È%token“²de nitions“needed“to“iden¸ãtify“terminals“in“the“formattedŽ¡‘@¿®grammar‘UU le.ŽŽŸK’×lx47ŽŽŒ‹0©ƒ ½\È ýN£8‘63ײ48’Êà¤ÃCHAPTER–UU6.‘ÇFUTURE“W¸ãORKŽŽ ˜G ý„‘63ׯChange›ÕTprett•®9yprin“ting˜grammar˜format.ŽŽ’²It–Èw¸ãould“bšGe“nice“to“b˜e“able“to“insertŽ© ‘O3Ùformat–UUcommands“directly“inš¸ãto“the“grammar“rules,“lik˜e“for“example“in:ޤ‘Y3ÚÈWHILE–?ýexpr“DO“ÎindentŽ‘&ÊôÈstmt“ÎoutdentŽ‘+çcfor–ÿ}'c“eŽ‘Fz,¸ŽŽŽ‘L–¢!“ÈstmtŽ¡‘O3Ù²This–yÌis“a“pGoinš¸ãt“that“e ects“fundamen˜tals“of“the“Îbuild‘‰ffŽ‘®pp‘ÿ}'arseŽ‘;Ït²function.‘ß,Otherަ‘O3Ùparts–ìof“Pretzel“are“not“in•¸ãv“olv“ed.‘ÎŒThis–ìis“a“cš¸ãhange“that“w˜ould“bšGe“go˜o˜d“forަ‘O3Ùnew–UUusers,“since“this“w•¸ãa“y–UUof“spGecifying“the“grammar“is“m•¸ãuc“h–UUmore“in•¸ãtuitiv“e.ޤ‘63ׯInclude–ÕT les“for“grammars.ŽŽ’²As–8ãparts“of“prett•¸ãyprin“ting–8ãgrammars“oGccur“frequen¸ãtlyަ‘O3Ùin–™Lmanš¸ãy“di eren˜t“programming“languages“(suc˜h“as“the“formatting“of“expres-ަ‘O3Ùsions)–Úµit“w¸ãould“bšGe“nice“to“b˜e“able“to“include“ les“that“con¸ãtain“these“de nitionsަ‘O3Ùwith–!üa“simple“command“in“the“formatted“tok¸ãen“and“formatted“grammar“ les.ަ‘O3ÙOn–éña“more“abstract“lev¸ãel“one“could“think“of“a“notion“of“moGdules“of“grammars,ަ‘O3Ùi.e.–ANparts“of“a“grammar“that“can“bšGe“called“with“argumen¸ãts“to“suit“lo˜cal“demandsަ‘O3Ù(\grammar–KÞtemplates"?).‘nŸBut“it“is“still“an“unansw¸ãered“question“whether“thisަ‘O3Ùis–Çfpractical,‘ãêbšGecause“of“the“lac¸ãk“of“metho˜d“to“sp˜ecify“the“inš¸ãterface“of“suc˜h“aަ‘O3ÙmoGdule.Ž¡‘63ׯEnhance–ÕTÈnoweb“ÆsuppQÇort.ŽŽ’±üå²This–ËÑincludes“managing“mš¸ãultiple“prett˜yprin˜ting“ ltersަ‘O3Ùand–cMautomatically“selecting“a“ lter“for“the“righš¸ãt“language“(if“y˜ou“mix“languagesަ‘O3Ùin–;¼Ènoweb“² les).‘i?The“Ènoweb“²suppGort“seems“the“place“where“the“most“w¸ãork“canަ‘O3ÙbGe–UUdone“to“get“a“practical“system.ŽŸ‘63×Suggestions–UUare“alw•¸ãa“ys‘UUw“elcome.ŽŽŽŒ‹1·X ½\È ýN£8 ˜G ýÏq%‘'¿¬ÊChapter‘Ç 7ŽŸ2q%‘'¿¬ÅReferenceŽŸ4q$‘@¿®²\I‘ýGused–ýrto“think“that“prett•¸ãyprin“ting›ýrw“as˜the˜cats˜meo“w,‘'ybut˜after˜bGe-ޤ ‘@¿®coming–‹a“bit“accustomed“to“Ènoweb“²I›ŠÂ nd“that“a“ÈCWEB˜²prin¸ãtout“loGoksŽ¡‘@¿®somewhat–UUlik¸ãe“gibbGerish."ŽŸâI‘@¿®Barry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŸÄ“‘'¿¬This–×”cš¸ãhapter“con˜tains“a“complete“and“detailed“reference“of“the“Pretzel“system.‘GÜThisŽ¡‘'¿¬is–¬Ìinformation“that“mostly“is“also“conš¸ãtained“in“the“man˜ual“pages“Èpretzel(1)“²andŽ¡‘'¿¬Èpretzel-it(1)².ŽŸ#j ‘'¿¬Ì7.1Ž‘L¦The–ffConcept“of“PretzelŽŸ¹­‘'¿¬²The–Féconcept“of“Pretzel“is“visualized“in“ gure“7.1.‘F‚F‘ÿ*ªrom“a“formal“formatting“de-Ž¡‘'¿¬scription–ðÌof“a“programming“language“µP‘c²,‘çPretzel“generates“a“prett•¸ãyprin“ting‘ðÌfunctionŽ¡‘'¿¬that–ûcan“bšGe“used“to“prett•¸ãyprin“t–ûsource“co˜de“in“µP‘c².‘w¸T‘ÿ*ªo“get“the“actual“prett•¸ãyprin“t-Ž¡‘'¿¬ing–Òprogram,‘Ÿ±yš¸ãou“only“ha˜v˜e“to“supply“a“main“program“(or“use“the“one“that“comesŽ¡‘'¿¬with–¾ýPretzel).‘®¾If“the“w•¸ãa“y–¾ýof“prett•¸ãyprin“ting–¾ýneeds“to“bGe“c¸ãhanged,‘fthe“user“onlyŽ¡‘'¿¬needs–éto“c¸ãhange“formal“parts“in“the“input“and“use“Pretzel“again“to“get“an“enhancedŽ¡‘'¿¬prett•¸ãyprin“ter.ŽŸ q%‘6¿¬Figure–&ö7.2“on“page“51“shoš¸ãws“the“generating“proGcess“in“sligh˜tly“more“detail.‘bRTheŽ¡‘'¿¬ gure–•shoš¸ãws“that“the“program“Pretzel“doGesn't“generate“a“prett˜yprin˜ter“immediately;Ž¡‘'¿¬what–óyit“došGes“is“to“pro˜duce“co˜de“that“can“b˜e“turned“inš¸ãto“a“ÇCŸÿ²++Ž‘µprett˜yprin˜ting“classŽ¡‘'¿¬with–UUthe“help“of“t•¸ãw“o‘UUtoGols:ŽŸSn‘'¿¬Æ exŽŽ‘>zQ²A–UUPOSIX.2“complian¸ãt“lexical“analyser“generator.ŽŸÄ’‘'¿¬ÆBisonŽŽ‘HÌn²A‘uÅPOSIX.2–uÍcomplianš¸ãt“parser“generator.‘Ó/The“v˜ersion“used“with“Pretzel“hasŽ¡‘@¿®to–UUproGduce“ÇCŸÿ²++Ž‘ã‘complian¸ãt“source.Ž ‡XÚŸÞ9ŸÕiè’¼|pretzelŽŽŽ’©æŸï¾F‰feAÓ²ŸAº„AºfeŸ÷ß#Ž‘Aè„AºfeŽžfe‰feAÓ²ŽŽŽ’ÇçŸêS„ ÝfeŽ’ÈPŸêS¬?ŽŽ’”ŸƒŸøE‰„ÌÌAº‘öž™šóäO£ linew10­-ŽŽ’î ŸøE‰„Ì̬ø‘öž™š-ŽŽ’´¼’ŸÌ…3‰fe)qŸAº„AºfeŸ÷ß#Ž‘(¤Q„AºfeŽžfe‰fe)qŽŽŽ’ÇçŸÇõ„ Ö|feŽ’ÈPŸÇõ¬?ŽŽŸ·œ’£,[²formal‘UUdescriptionŽŽŽŸø¢û’®“yprett•¸ãyprin“terŽŽŽŸú”‘ÉT‘ÿ*ªextŽŽŽŸð‚’¿óprett•¸ãyprin“tedŽŽŽ’¢ðtextŽŽŽŽŽŽŽŸ ’—Figure–UU7.1:‘qÇThe“concept“of“Pretzel.ŽŽŽŽŸK’×lx49ŽŽŒ‹2¾ä ½\È ýN£8‘63ײ50’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63ײUsers–üthat“are“already“familiar“with“the“basics“of“bšGoth“to˜ols“will“ nd“it“easier“toޤ ‘63×read–)othe“folloš¸ãwing“text“bGecause“the“w˜a˜y“of“spGecifying“input“to“Pretzel“is“quite“closeŽ¡‘63×to–mthe“w•¸ãa“ys–mused“bš¸ãy“them.‘¸ýHo˜w˜ev˜er,‘sthis“text“aims“at“pGeople“who“don't“ha˜v˜e“suc˜hŽ¡‘63×knoš¸ãwledge–UUand“will“explain“ev˜erything“that“is“necessary‘ÿ*ª.Ž© ˆ‡‘E3×Also–UUvisible“from“this“ gure“is“that“Pretzel“creates“t•¸ãw“o‘UUthings:ŽŸ"‘E3ظŽŽŽ‘O3Ù²A›UUprett•¸ãyprin“ting˜scanner˜class˜andŽŸ"‘E3ظŽŽŽ‘O3Ù²a›UUprett•¸ãyprin“ting˜parser˜class˜(con“taining˜the˜actual˜prett“yprin“ter).ŽŸ"‘E3×The›áprett•¸ãyprin“ting˜parser˜is˜the˜actual˜prett“yprin“ter˜function˜that˜y“ou˜normallyŽ¡‘63×w•¸ãan“t–³to“get“when“using“Pretzel.‘ŠÈThe“prett•¸ãyprin“ting–³scanner“is“used“b¸ãy“the“parserŽ¡‘63×and–!utakš¸ães“care“of“the“tok˜en“formatting.‘Ö'Both“parts“are“separate“moGdules“with“aŽ¡‘63×wš¸ãell–.gde ned“in˜terface“and“can“bGe“used“individually‘ÿ*ª.‘dÍHence,‘60y˜ou“can“write“y˜our“o˜wnŽ¡‘63×scanner–¬|or“parser“if“yš¸ãou“really“need“features“that“the“ones“proGduced“b˜y“Pretzel“don'tŽ¡‘63×ha•¸ãv“e.ŽŸÒ‘63×Í7.1.1Ž‘_s×The–€Input“FilesŽŸsj‘63ײThe–Ãåwš¸ãord“\prett˜y"“is“v˜ery“sub‘Ž8jectiv˜e“and“so“programming“language“source“coGde“canŽ¡‘63×bGe–#prinš¸ãted“in“a“\prett˜y"“kind“of“fashion“in“almost“in nitely“man˜y“w˜a˜ys,‘ž×accordingŽ¡‘63×to–X³the“taste“and“preferences“of“the“user.‘{âIf“the“task“of“prett•¸ãyprin“ting–X³is“handedŽ¡‘63×o•¸ãv“er–›Œto“the“computer,‘­the“user“mš¸ãust“spGecify“in“detail“all“of“his“wishes“to˜w˜ards“theŽ¡‘63×appGearance–UUof“the“output“of“the“prett•¸ãyprin“ter.ަ‘E3×T‘ÿ*ªo–%©generate“a“prett•¸ãyprin“ter,‘Y¾Pretzel–%©needs“t•¸ãw“o–%©descriptions“that“it“expGects“toŽ¡‘63× nd–UUin“t•¸ãw“o›UUdi eren“t˜ les:ŽŸ"‘63ׯA–ÕTformatted“tok®9en“ le.ŽŽ’®Ú̲This–º le“should“con¸ãtain“all“information“concerning“theŽ¡‘O3Ùindividual–UUformatting“of“tokš¸ãens“(i.e.“iden˜ti ers,“reserv˜ed“w˜ords,“etc.).ŽŸ"‘63ׯA–ÕTformatted“grammar“ le.ŽŽ’ÀÊIJThis–’4 le“should“conš¸ãtain“a“prett˜yprin˜ting“grammar,Ž¡‘O3Ùi.e.–­a“con¸ãtext“free“grammar“enhanced“with“formatting“commands.‘_äThis“infor-Ž¡‘O3Ùmation–’yis“necessary“to“handle“the“more“global“aspGects“of“prett•¸ãyprin“ting‘’ythatŽ¡‘O3Ùneed–m›information“abGout“the“language“conš¸ãtext“(i.e.“inden˜tation,‘³¬line“breaks,Ž¡‘O3Ùetc.).ŽŸ"‘63×The–Ëdname“of“the“ rst“ le“migh¸ãt“bšGe“a“little“misleading,‘(çsince“it“do˜esn't“con¸ãtainŽ¡‘63×formatted–¸Btokš¸ãens.‘=lInstead“it“tells“y˜ou“what“y˜ou“will“get“from“the“de nitions“therein.Ž¡‘63×A‘Jùname–K=likš¸ãe“\tok˜en“formatting“ le"“migh˜t“ha˜v˜e“bšGeen“a“little“b˜etter,‘€ubut“the“similarit¸ãyŽ¡‘63×in–—¨names“bšGet•¸ãw“een–—¨the“t•¸ãw“o–—¨input“ les“sounded“go˜o˜d“and“seemed“to“outpla¸ãy“this“smallŽ¡‘63×inconsistency‘ÿ*ª.ަ‘E3×The–HVspšGecial“formats“of“these“t•¸ãw“o–HV les“are“describ˜ed“later“in“section“7.2.‘JÉTheŽ¡‘63×in¸ãterface–UUto“the“generated“Pretzel“classes“is“describGed“in“detail“in“section“3.2.ŽŸ#æ‘63×Ì7.2Ž‘[:The–ffF‘þ¦format“of“the“Input“FilesŽŸå1‘63ײNo•¸ãw›¶w“e˜turn˜to˜a˜vital˜thing˜for˜the˜user˜of˜Pretzel:‘",The˜format˜of˜the˜Pretzel˜inputŽ¡‘63× les.‘l³Here–Fthe“user“has“to“put“a“formal“description“of“the“underlying“programmingŽ¡‘63×language–ôand“(with“the“help“of“format“commands)“state“ho¸ãw“its“text“should“bGeŽ¡‘63×formatted.ަ‘E3×W‘ÿ*ªe›×'ha•¸ãv“e˜seen˜that˜Pretzel˜tak“es˜t“w“o˜input˜ les:‘ujThe˜formatted˜tok“en˜ le˜andŽ¡‘63×the–¤“formatted“grammar“ le.‘6ÜW‘ÿ*ªe“suggest“to“use“the“sux“`È.ft²'“for“a“formatted“tok¸ãenŽ¡‘63× le–UUand“`È.fg²'“for“a“formatted“grammar“ le.ŽŽŽŒ‹3Èz ½\È ýN£8‘'¿¬Ã7.2.‘ÇTHE–UUF¸ãORMA‘ÿ*ªT“OF“THE“INPUT“FILES’”'¹²51ŽŽ ˜G þjÄ0ŸÞ9’õΟŽ3ê„ ƒtfeŽ’ )ŸŽ3ê¬?ŽŽ’õΟ±lý„b—feŽ’ )Ÿ±lý?ŽŽ’õΟ÷ß#„(¤QfeŽ’ )Ÿ÷ß#?ŽŽ ÿBV†’Zògrammar‘UU leŽŽŽŽ ÿhE8’¨ýBison‘UUsourceŽŽŽŽŸ–TÇ’ >RC++‘UUcoGdeŽŽŽŽŸ¼Cy’pprett•¸ãyprin“tingŽŽŽŽ’6ëprett•¸ãyprin“terŽŽŽŽ ÿR˜@’%”>Îpr‘ÿ}'etzelŽŽŽŽŸ€§Ï’%”>BisonŽŽŽŽŸ©L ’%”>CCŽŽŽŽ ÿ7€ ’ žQ²formattedŽŽŽŽŸÇõ’ÅpparserŽŽŽŽŸ‹~K’ÍáʱcommonŽŽŽŽŸ“Ÿ(’ÆŽtokÈãen‘±ÈheaderŽŽŽŽ’õΠÿ]n¼„b—feŽ’ ) ÿ]n¼¬?ŽŽ’˜|À ÿ`$[„6feŽ’˜¯ò ÿ`$[?ŽŽŸÇõ’ˆA·²scannerŽŽŽŽ’˜|ÀŸŽ3ê„ ƒtfeŽ’˜¯òŸŽ3ê¬?ŽŽ’˜|ÀŸ´"œ„b—feŽ’˜¯òŸ´"œ?ŽŽ’˜|ÀŸäçÊ„6feŽŽ’˜¯òŸåü„fdX1‘öžÌÎ-ŽŽ ÿuÅ¢’ÈѰ.ŽŽŽ ÿuÅ¢’þ¨.ŽŽŽ ÿuÅ¢’ 4.ŽŽŽ ÿuÅ¢’jV.ŽŽŽ ÿuÅ¢’ú -.ŽŽŽ ÿuÅ¢’òÖ.ŽŽŽ ÿuÅ¢’ë Û.ŽŽŽ ÿuÅ¢’ãA².ŽŽŽ ÿuÅ¢’Ûw‰.ŽŽŽ ÿuÅ¢’Ûwˆ.ŽŽŽ ÿ|‹¯’Ûwˆ.ŽŽŽŸƒQ¼’Ûwˆ.ŽŽŽŸ˜þµ’Ûwˆ.ŽŽŽŸžió’Ûwˆ.ŽŽŽ’ž0Ÿžu¤¬ŽŽŸžió’Ûwˆ°.ŽŽŽŸžió’Ó­_.ŽŽŽŸžió’Ëã6.ŽŽŽŸžió’Ä .ŽŽŽŸžió’¼Nä.ŽŽŽŸžió’´„».ŽŽŽŸži󒬺’.ŽŽŽŸžió’¤ði.ŽŽŽ ÿBV†’„¯ï²tok¸ãen‘UU leŽŽŽŽ ÿhE8’ºš ex‘UUsourceŽŽŽŽŸ–TÇ’ÅDC++‘UUcoGdeŽŽŽŽŸ¼Cy‘y÷ prett•¸ãyprin“tingŽŽŽŽ ÿR˜@’›e‘Îpr‘ÿ}'etzelŽŽŽŽŸ€§Ï’›e‘ exŽŽŽŽŸ©L ’ž0CCŽŽŽŽŸâ2+’ÁTC²is–UUcalled“b¸ãyŽŽŽŽ ÿ7€ ’ƒ%CformattedŽŽŽŽŽŽŽŽŸ ‘9/öFigure–UU7.2:‘qÇThe“currenš¸ãt“proGcess“of“generating“a“prett˜yprin˜ter“with“Pretzel.ŽŽŽŸ£‘'¿¬Í7.2.1Ž‘Pÿ¬The–€F›þàormatted“T˜ok en“FileŽŸ„Ï‘'¿¬²The–­`formatted“tokš¸ãen“ le“con˜tains“a“list“of“tok˜en“de nitions“with“their“correspGondingޤ ‘'¿¬\prett•¸ãyprin“ted"–+iform.‘cÎThe“prett•¸ãyprin“ted–+iform“of“a“tok¸ãen“will“bGe“called“an“ÎattributeŽ¡‘'¿¬²or–UUa“Îtr‘ÿ}'anslation².ޤ Q‘6¿¬The–UUgeneral“outline“of“the“formatted“tok¸ãen“ le“isŽ©!E‘1¿­Îde–ÿ}'clar“ationsŽŽ¡‘1¿­È%%Ž¡‘1¿­Îtoken‘“çde nitionsŽŽŸô‘'¿¬²Normally‘ÿ*ª,‘vothe›oÑÎde–ÿ}'clar“ations˜²part˜is˜empt¸ãy–ÿ*ª.‘Á:Y“ou˜can˜put˜a˜general˜description˜of˜theޤ ‘'¿¬ le–-Phere“(as“a“ÇC“²commenš¸ãt)“and“rede nitions“of“the“default“in˜terface“go“here“as“w˜ellŽ¡‘'¿¬(see–UUsection“3.2“for“more).ŽŸ Q‘6¿¬The–{|Îtoken‘Ë}de nitions“²section“of“the“formatted“tokš¸ãen“ le“con˜tains“a“series“of“tok˜enŽ¡‘'¿¬de nitions–UUof“the“form:ަ‘1¿­Îp‘ÿ}'atternŽ‘eOctokenŽ’‘U)¸fÎattributeŽ‘%­Ë¸gŽŸô‘'¿¬²The–{ïÎp‘ÿ}'attern“²mš¸ãust“bGe“a“v‘ÿqÇalid“regular“expression“(in“terms“of“Èflex²)“and“m˜ust“bGeŽ¡‘'¿¬unindenš¸ãted.‘ašThe–OñÎtoken“²spGeci es“the“sym˜bGolic“name“of“the“tok˜en“for“the“patternŽ¡‘'¿¬and–õ²bGegins“at“the“ rst“non-whitespace“cš¸ãharacter“after“the“pattern.‘QæThe“tok˜en“nameŽ¡‘'¿¬mš¸ãust–)|bGe“a“legal“name“for“an“iden˜ti er“in“ÇP‘ÿ ascal“²notation“and“Îmust–kb›ÿ}'e“al‘‚Øl“in“upp˜erŽ¡‘'¿¬c‘ÿ}'ase².‘qÇ(Underlines–UUare“allo•¸ãw“ed–UUbut“not“at“the“bGeginning“of“a“w¸ãord.)Ž© Q‘6¿¬The–°Îattribute“²for“this“tokš¸ãen,‘Ç^that“is“it's“prett˜yprin˜ted“form,‘Ç^consists“of“all“textŽ¡‘'¿¬bšGet•¸ãw“een–Øthe“t•¸ãw“o–Øcurling“brac•¸ãk“ets–Ø`¸f²'“and“`¸g²'.‘H/A¸ãttributes“can“b˜e“either“simple“stringsŽ¡‘'¿¬(surrounded–Šcbš¸ãy“double“quotes)“or“format“commands“(lik˜e“Îfor–ÿ}'c“eŽ‘Ý/²,‘—¦ÎindentŽ‘â ²)“or“a“com-Ž¡‘'¿¬bination–¨kof“bGoth“joined“together“bš¸ãy“an“optional“`È+²'“sign.‘kA˜ttribute“de nitions“canŽ¡‘'¿¬co•¸ãv“er›`ƒsev“eral˜lines˜and˜the˜starting˜`¸f²'˜needn't˜stand˜on˜the˜same˜line˜as˜the˜tok“enŽ¡‘'¿¬de nition;‘tŒho•¸ãw“ev“er›Ïsubsequen“t˜lines˜m“ust˜bGe˜inden“ted˜with˜at˜least˜one˜blank˜orŽ¡‘'¿¬one–ÖÁtab.‘ö Aš¸ãttributes“can“also“con˜tain“ÇC‘Ö ²coGde.‘ö See“section“3.1“or“the“man˜ual“pageŽ¡‘'¿¬Èpretzel(1)–UU²for“details.ަ‘6¿¬If–0yš¸ãou“de ne“strings“as“part“of“an“attribute“de nition,‘7zy˜ou“ha˜v˜e“to“spGecify“themŽ¡‘'¿¬in–WÇa“ÇC“²kind“of“fashion,‘˜ci.e.“y¸ãou“can“insert“newlines“and“tabs“with“`È\n²'“and“`È\t²'.ŽŽŽŒ‹4×€ ½\È ýN£8‘63ײ52’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63ײBut–ïòif“yš¸ãou“w˜an˜t“to“insert“a“bac˜kslash“in˜to“a“string,‘V™y˜ou“m˜ustn't“forget“to“putޤ ‘63×t•¸ãw“o›ÀÀbac“kslashes˜(`È\\²')˜in“to˜the˜input˜ le.‘´This˜is˜espGecially˜notew“orth“y˜if˜y“ou˜areŽ¡‘63×using–¾PT‘þU>Ÿ'EŽ›ãxX“as“t¸ãyp•Gesetter,‘ØŽb“ecause–¾PT‘þU>Ÿ'EŽ˜X“uses“a“bacš¸ãkslash“as“a“pre x“for“t˜ypGesettingŽ¡‘63×commands.Ž© ™ë‘E3×If–rthe“de nition“of“the“attribute“is“omitted“Pretzel“creates“an“attribute“for“thisŽ¡‘63×pattern–cWbš¸ãy“default.‘›ÌThe“default“attribute“consists“of“the“string“con˜taining“the“textŽ¡‘63×matc•¸ãhed›UUb“y˜the˜correspGonding˜pattern.ަ‘E3×The–&duser“himself“maš¸ãy“also“refer“to“the“matc˜hed“text“b˜y“using“the“sequence“`È**²'.Ž¡‘63×Th¸ãusŽ©ÍÁ‘@³ÑÈ"foo"‘$¿ëBARŽ¡‘@³Ñ"foo"‘$¿ëBAR‘?ñ{–?ý**“}Ž¡‘@³Ñ"foo"‘$¿ëBAR‘?ñ{–?ý"foo"“}ަ‘63ײall›UUha•¸ãv“e˜the˜same˜meaning.Ž© ™ë‘E3×Y‘ÿ*ªou–7Çcan“use“a“`È|²'“sign“as“a“tokš¸ãen“name;‘©this“signals“that“the“curren˜t“regularŽ¡‘63×expression–h?has“the“same“tokš¸ãen“name“(and“also“the“same“attribute)“as“the“tok˜enŽ¡‘63×spGeci ed–g³in“the“folloš¸ãwing“line“(empt˜y“lines“are“ignored).‘¨àAn“attribute“de nitionŽ¡‘63×bGehind–jwa“`È|²'“is“illegal.‘±.Ho•¸ãw“ev“er›jwy“ou˜ma“y˜spGecify˜regular˜expressions˜with˜neither˜aŽ¡‘63×tokš¸ãen–UUname“nor“an“attribute“to“giv˜e“a“default“rule“or“to“eat“up“whitespace.ަ‘E3×The–¯(folloš¸ãwing“examples“are“all“legal“tok˜en“de nitions“(and“please“note“the“dotŽ¡‘63×in–UUthe“v¸ãery“last“line):Ž©g¬‘@³ÑÈ[0-9]‘9¿ßDIGITŽ¡¡‘@³Ñ"{"‘D?ÙOPEN‘9¿ß{–?ý"\\{"“indent“force“}Ž¡¡‘@³Ñ[a-z][a-z0-9]*‘ úID‘D?Ù{–?ý"{\\it“"“+“**“+“"}"“}Ž¡¡‘@³Ñ"function"‘î|Ž¡‘@³Ñ"procedure"–?ñPROC_INTRO“{–?ýbig_force“**“}Ž¡¡‘@³Ñ[\t\‘?ý\n]‘)ÿè|Ž¡‘@³Ñ.ަ‘E3ײThe–U¬declarations“and“the“tokš¸ãen“de nitions“m˜ust“bGe“separated“b˜y“a“line“con˜tainingŽ¡‘63×only–UUthe“t•¸ãw“o›UUc“haracters˜È%%².‘qÇSo˜the˜shortest˜pGossible˜formatted˜tok“en˜ le˜isޤÍÁ‘EóÎÈ%%Ž¡‘63ײbut–UUthis“došGesn't“seem“of“an¸ãy“use,“do˜es“it?ŽŸ.Õ‘63×Í7.2.2Ž‘_s×The–€F‘þàormatted“Grammar“FileŽŸ“È‘63ײIn–Þthe“formatted“grammar“ le“the“user“encoGdes“the“general“prett•¸ãyprin“ting‘Þgrammarޤ ‘63×for–w&the“programming“language.‘×9This“is“done“bš¸ãy“spGecifying“a“con˜text“free“grammarŽ¡‘63×of–WIthe“language“and“b¸ãy“adding“information“abGout“the“creation“of“new“attributes“inŽ¡‘63×ev¸ãery‘UUrule.Ž© ™ë‘E3×The–Çùformatted“grammar“ le“is“the“second“and“last“input“to“the“Pretzel“program.Ž¡‘63×Its–UUgeneral“outline“loGoks“lik¸ãe“this:ŽŸ—‘@3ØÎtoken‘“çde–ÿ}'clar“ationsŽŽ¦‘@3ØÈ%%ަ‘@3ØÎgr‘ÿ}'ammar‘“çrulesŽŽŽŽŒ‹5ç! ½\È ýN£8‘'¿¬Ã7.2.‘ÇTHE–UUF¸ãORMA‘ÿ*ªT“OF“THE“INPUT“FILES’”'¹²53ŽŽ ˜G ý„‘6¿¬The›»æÎtoken‘¿de–ÿ}'clar“ations˜²section˜ma•¸ãy˜bGe˜empt“y˜and˜the˜separator˜bGet“w“een˜the˜t“w“oޤ ‘'¿¬parts–¯of“the“ le“(È%%²)“mš¸ãust“appGear“uninden˜ted“on“a“single“line“b˜y“itself.‘Before“w˜eŽ¡‘'¿¬lošGok–UUat“these“declarations,“let's“ha•¸ãv“e–UUa“lo˜ok“at“the“grammar“rules.Ž¡‘6¿¬The–ÓÎgr‘ÿ}'ammar‘Kprules“²section“conš¸ãtains“the“collection“of“rules“of“the“con˜text“freeŽ¡‘'¿¬grammar–ýAthat“can“bšGe“accompanied“b¸ãy“an“attribute“de nition.‘iŒA‘ýrule“is“sp˜eci edŽ¡‘'¿¬bš¸ãy–œûstating“the“resulting“tok˜en,‘îåa“colon“and“then“the“series“of“tok˜ens“whic˜h“willŽ¡‘'¿¬bGe–öreduced“bš¸ãy“this“rule.‘T#The“rule“is“ended“b˜y“a“semicolon.‘T#A‘õõbloGc˜k“de nition“inŽ¡‘'¿¬ÇP‘ÿ ascal–UU²for“example“mighš¸ãt“loGok“lik˜e“this:Ž©33‘2?¦Èblock–?ý:“BEGIN“stmt_list“ENDŽ¡‘2?¦;ަ‘6¿¬²F‘ÿ*ªolloš¸ãwing–.Bthe“tok˜en“list“on“the“righ˜t“side“of“the“colon“can“bGe“an“attribute“de n-Ž¡‘'¿¬ition;‘)¿this–ôde nition“states,‘!hoš¸ãw“the“translation“of“the“proGduced“sym˜bGol“is“obtainedŽ¡‘'¿¬from–UUthe“tokš¸ãens“on“the“righ˜t“side“of“the“rule.Ž¡‘6¿¬An–fDattribute“de nition“is“brac•¸ãk“eted–fDamidst“curling“brac•¸ãk“ets–fD`¸f²'“and“`¸g²'“and“canŽ¡‘'¿¬again–D}consist“of“strings“(in“double“quotes)“and“format“commands“or“bGoth“joinedŽ¡‘'¿¬together–mwith“`È+²'.‘[%But“here“yš¸ãou“can“also“refer“to“the“attributes“of“the“tok˜ens“on“theŽ¡‘'¿¬righš¸ãt–¸Kside“of“the“rule.‘š©This“is“done“in“a“sligh˜tly“a˜wkw˜ard“notation“with“a“n˜um˜bGerŽ¡‘'¿¬that–›“is“preceded“with“a“`È$²'“dollar“sign.‘3ÜThe“n•¸ãum“bšGers–›“refer“to“the“order“of“app˜earanceŽ¡‘'¿¬of–…Šthe“symš¸ãbGols“on“the“righ˜t“side“of“the“rule.‘fSo“`È$1²'“refers“to“the“ rst“tok˜en“of“theŽ¡‘'¿¬rule,–UU`È$2²'“to“the“second,“.–ªª.“.Ž¡‘6¿¬Again–¶attribute“de nitions“are“allo•¸ãw“ed–¶to“span“sevš¸ãeral“lines“and“strings“m˜ust“bGeŽ¡‘'¿¬spšGeci ed–UUin“ÇC“²manner.‘qÇThey“can“also“con¸ãtain“ÇC“²co˜de“as“describ˜ed“in“section“3.1.Ž¡‘6¿¬F‘ÿ*ªor–JØexample,‘ˆ8here“again“is“the“pšGossible“de nition“of“a“blo˜cš¸ãk“in“ÇP‘ÿ ascal²,‘ˆ8no˜wŽ¡‘'¿¬with–UUan“example“attribute“de nition:ަ‘2?¦Èblock–?ý:“BEGIN“stmt_list“END‘¿÷{“$1“+“$2“+“force“+“$3“}Ž¡‘2?¦;ަ‘6¿¬²The–)æattribute“of“a“Èblock“²will“therefore“consist“of“the“attributes“of“the“ÈBEGINŽ¡‘'¿¬²and–¸}Èstmt‘¡E‰ff&fŽ‘Ç«list“²tok¸ãens,‘ÑGjoined“together“with“a“Îfor–ÿ}'c“eŽ‘ÃÆ²command“and“the“translationŽ¡‘'¿¬of–UUthe“ÈEND“²tok¸ãen.Ž¡‘6¿¬The–Vžattribute“de nition“maš¸ãy“bGe“omitted.‘u£If“this“is“so,‘–ðPretzelwill“b˜y“defaultŽ¡‘'¿¬form–6Ûthe“attribute“of“the“prošGduced“sym¸ãb˜ol“from“the“simple“concatenation“of“theŽ¡‘'¿¬attributes–UUon“the“righ¸ãt“side“of“the“rule.‘qÇF‘ÿ*ªor“instanceަ‘2?¦Èstmt–?ý:“block“SEMIŽ¡‘2?¦;ަ‘'¿¬²means–UUthe“same“as:ަ‘2?¦Èstmt–?ý:“block“SEMI‘$¿ë{“$1“+“$2“}Ž¡‘2?¦;ަ‘6¿¬²Of–`ücourse“yš¸ãou“ma˜y“also“ha˜v˜e“empt˜y“righ˜t“sides“of“a“rule“(to“proGduce“things“outŽ¡‘'¿¬of–£ßnothing)“or“simply“concatenate“t•¸ãw“o–£ßor“more“rules“resulting“in“the“same“sym¸ãbGolŽ¡‘'¿¬with–UUa“`È|²'.‘qÇSo“the“follo¸ãwing“are“legal“rules:ަ‘2?¦Èstmt_list‘¿÷:‘s¾{–?ýforce“}Ž¡‘q?‚|–?ýstmt_list“stmt“SEMI‘ ú{“$1“$2“$3“force“}Ž¡‘2?¦;ަ‘6¿¬²T‘ÿ*ªo–yend“this“subsection,‘,wš¸ãe“ha˜v˜e“to“return“to“the“Îtoken‘2Ede–ÿ}'clar“ations–y²section“ofŽ¡‘'¿¬the–ø×formatted“grammar“ le.‘RóHere“wš¸ãe“ha˜v˜e“to“insert“a“spGecial“line“for“ev˜ery“terminalŽ¡‘'¿¬tok¸ãen–ó§that“appGears“in“the“grammar“rules.‘Q8These“de nitions“are“of“the“form“`È%tokenŽ¡‘'¿¬ÎtokennameŽ‘WD7²'.‘óThis–€rpart“of“the“formatted“grammar“ le“is“o•¸ãw“ed–€rto“Bison“and“shouldŽ¡‘'¿¬bGe›UUremo•¸ãv“ed˜in˜subsequen“t˜v“ersions.ŽŽŽŒ‹6ñ· ½\È ýN£8‘63ײ54’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63×Í7.2.3Ž‘_s×Commen ts–€and“Co`deŽ©­m‘63ײThere–Ôis“a“vš¸ãery“simple“w˜a˜y“of“putting“commen˜ts“in˜to“the“formatted“tok˜en“andޤ ‘63×formatted–r grammar“ les.‘ÇâThis“is“done“in“a“ÇCŸÿ²++Ž‘Ekind“of“manner“b¸ãy“preceding“theŽ¡‘63×commenš¸ãt– ƒwith“a“double“slash“(`È//²').‘SQAll“c˜haracters“bGet˜w˜een“this“sign“and“the“endŽ¡‘63×of–UUthe“line“are“ignored“b¸ãy“pretzel.ŽŸ $‘E3×In–à bšGoth“ les“y¸ãou“can“put“additional“ÇCŸÿ²++Ž‘nGco˜de“b˜efore“and“after“the“de ni-Ž¡‘63×tions/grammar–kçsections.‘µ}If“yš¸ãou“w˜an˜t“to“insert“coGde“at“the“end“of“y˜our“ le,‘±‹y˜ouŽ¡‘63×ha•¸ãv“e–¶Ýto“put“a“second“`È%%²'“on“a“line“b¸ãy“itself“and“put“the“cošGde“b˜ehind“it.‘–^ÇC²/ÇCŸÿ²++ŽŽ¡‘63×Co•Gde›Õßb“efore˜the˜de nitions/rules˜section˜has˜to˜b“e˜tied˜in˜with˜a˜`%¸f²',‘ö`%¸g²'˜pair.Ž¡‘63×Inserting–í€extra“cošGde“is“in¸ãteresting“for“p˜eople“who“w•¸ãan“t–í€to“call“this“co˜de“from“withinŽ¡‘63×the–UUattribute“de nitions.‘qÇSee“section“3.1“for“details.ŽŸ!±°‘63×Ì7.3Ž‘[:Synopsis–ffof“Øpretzel“Ìand“Øpretzel-itŽŸ4‘63×Í7.3.1Ž‘_s×Üpretzel-itަ‘63ײThe–¹Fshell“script“Èpretzel-it“²uses“Pretzel“to“build“a“simple“prett•¸ãyprin“ter‘¹Fexecutable.Ž¡‘63×It–UUminimizes“building“a“Pretzel“prett•¸ãyprin“ter–UUto“just“one“shell“command.Ž© $‘E3×Y‘ÿ*ªou›ò§ha•¸ãv“e˜to˜pro“vide˜the˜same˜t“w“o˜input˜ les˜to˜Èpretzel-it˜²as˜to˜Pretzel.Ž¡‘63×These›úÙt•¸ãw“o˜ les˜are˜called˜the˜formatted˜tok“en˜ le˜(sux˜È.ft²)˜and˜the˜formattedŽ¡‘63×grammar–ûF le“(sux“È.fg²).›SÂBoth“ les“need“to“ha•¸ãv“e–ûFthe“same“pre x.˜F‘ÿ*ªrom“this“input,Ž¡‘63×Èpretzel-it–UU²generates“an“executable“prett•¸ãyprin“ter.ަ‘E3×T‘ÿ*ªo–UUget“to“knoš¸ãw“the“options,“t˜ypGeޤZm‘@³ÑÈpretzel-it‘?ý-hŽ¡‘63ײat–UUthe“command“line.‘qÇThe“full“usage“is:Ž¡‘@³ÑÈpretzel-it–?ý[-iqvdnh]“language“ppnameŽ¡‘63ײHere's–UUan“explanation“of“the“options:Ž¡‘63ׯ-iŽŽ‘B:ñ²Don't›UUremo•¸ãv“e˜in“termediate˜proGducts˜of˜pretzeling.ޤx’‘63ׯ-qŽŽ‘Eð²Run‘UUquietly‘ÿ*ª.Ž¡‘63ׯ-vŽŽ‘Eð²V‘ÿ*ªerb•Gose›UUmo“de,˜prin¸ãt˜shell˜commands˜b“efore˜in•¸ãv“oking˜(for˜debugging).Ž¡‘63ׯ-dŽŽ‘El·²T‘ÿ*ªurn›H;prett•¸ãyprin“ter˜debugging˜features˜on˜b“y˜default˜(for˜debugging˜the˜pret-Ž© ‘O3Ùt•¸ãyprin“ting‘UUgrammar).Ž¡‘63ׯ-hŽŽ‘El·²Prin¸ãt–UUfull“usage“message.Ž¡‘63ׯ-nŽŽ‘El·²No•¸ãw“eb–ø(mošGde,‘ Êwill“pro˜duce“a“prett•¸ãyprin“ting–ø( lter“Èppname“²compatible“to“Normanަ‘O3ÙRamsey's–Ènoweb“²literate“programming“system.‘^_The“ lter“can“bGe“inserted“in¸ãtoަ‘O3Ùthe–UUÈnoweb“²pipGeline“using“Ènoweave²'s“È-filter“²option.ޤZm‘63×See–UUalso“the“manpage“Èpretzel-it“²and“c¸ãhapters“2“and“4.ŽŸž"‘63×Í7.3.2Ž‘_s×ÜpretzelŽŸ­m‘63ײPretzel–UUis“in•¸ãv“ok“ed›UUb“y˜t“ypingŽ¡‘@³ÑÈpretzelŽ¡‘63ײat–žthe“command“line.‘AêThe“full“usage“of“Pretzel“can“bGe“obtained“using“the“È-h“²option.ަ‘63×It‘UUis:ŽŽŽŒ‹7¨ ½\È ýN£8‘'¿¬Ã7.3.‘ÇSYNOPSIS–UUOF“ÈPRETZEL“ÃAND“ÈPRETZEL-IT’Рײ55ŽŽ ˜G ý„‘2?¦Èpretzel–?ý[-qtgdh]“[-o“outfile]“(prefix“|“file1“file2)ޤ‘'¿¬²Here's–UUan“explanation“of“the“options:Ž¡‘'¿¬Æ-qŽŽ‘6¦Å²Run–UUquietly“(no“screen“output).Ž¡‘'¿¬Æ-tŽŽ‘5 â²ProGcess–UUformatted“tok¸ãen“ le“only‘ÿ*ª.Ž¡‘'¿¬Æ-gŽŽ‘6Tþ²ProGcess–UUformatted“grammar“ le“only‘ÿ*ª.Ž¡‘'¿¬Æ-dŽŽ‘6øŒ²Run–ûšin“debug“moGde“(i.e.“prin¸ãt“out“debugging“information“on“the“screen“whileŽ© ‘@¿®running).Ž¡‘'¿¬Æ-hŽŽ‘6øŒ²Sho¸ãw–UUfull“usage.Ž¡‘'¿¬Æ-o‘ÕTout leŽŽ‘Y¡d²Names–UUof“the“prošGduced“output“ les“b˜egin“with“\out le".Ž¡‘'¿¬The–G§options“È-t“²and“È-g“²are“mš¸ãutually“exclusiv˜e,‘„;i.e.“y˜ou“can't“c˜hošGose“b˜oth“at“theަ‘'¿¬same‘UUtime.ަ‘6¿¬The–žcommand“line“parameters“ha•¸ãv“e›ždi eren“t˜meanings˜depGending˜on˜whetherަ‘'¿¬one–€rore“t•¸ãw“o–€rnames“are“giv¸ãen.‘óIf“there“is“only“one“parameter,‘‹9it“spGeci es“the“pre xަ‘'¿¬of–EcbGoth“formatted“tok¸ãen“and“formatted“grammar“ les.‘lvThe“suxes“`È.ft²'“and“`È.fg²'ަ‘'¿¬are–%“assumed.‘â€But“if“there“are“t•¸ãw“o–%“parameters“at“the“command“line,‘Y¢Pretzel“willަ‘'¿¬takš¸ãe–ô‡the“ rst“as“full“name“of“the“formatted“tok˜en“ le“and“the“second“as“full“name“ofަ‘'¿¬the–¨Kformatted“grammar“ le.‘j¨In“this“case,‘½the“output“ les“will“get“a“default“name.ަ‘'¿¬The–UUoutput“ les“will“ha•¸ãv“e–UUendings“`È.l²'“(tok¸ãen“ le)“and“`È.y²'“(grammar“ le).ŽŽŽŒ‹8 L ½\È ýN£8‘63ײ56’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜GŽŒ‹9/ ½\È ýN£8 ˜G ýÔ,‘'¿¬ÅBibliograph‘ÿ8õyŽŸ5‚~‘,¿­²[1]ŽŽ‘ÃURL:Ž¡‘When˜to˜use˜prett“yprin“ting.‘ >P“osting˜inŽ¡‘JÂÈcomp.programming.literate²,‘ ÚòOctobGer–1994.‘ûVCorrect“sub‘Ž8ject“headerŽ¡‘JÂmighš¸ãt–UUbGe“di eren˜t.“Date“here:‘qÇ5“Oct“1994.ަ‘63×[59]ŽŽ‘JÂR.›ÅçSco•¸ãw“en,–â—D.˜Allin,“A.˜L.˜Hillman,“and˜M.˜Shimell.‘…"SO¸ãAP–ÅÂ{˜A“program˜whic¸ãhŽ¡‘JÂdoGcumen¸ãts–†Ÿand“edits“Algol60“programs.‘ûÎThe–Õ¼Computer“Journal²,‘¯÷14(2):133{135,Ž¡‘JÂ1971.ަ‘63×[60]ŽŽ‘JÂMarc– v‘ÿqÇan“Leeu•¸ãw“en.›b When– to“use“prett•¸ãyprin“ting.˜P“osting‘ inŽ¡‘JÂÈcomp.programming.literate²,‘·žOctobGer–pÃ1994.‘»Correct“sub‘Ž8ject“header“migh¸ãtŽ¡‘JÂbGe–UUdi eren¸ãt.“Date“here:‘qÇ7“Oct“1994.ަ‘63×[61]ŽŽ‘JÂMarc–Tev‘ÿqÇan“Leeu•¸ãw“en.‘ÌDi erences›TebGet“w“een˜CWEB–T$and˜WEB“prett•¸ãyprin“ting˜gram-Ž¡‘JÂmars.›2sP¸ãosting––ñin“Ècomp.programming.literate²,‘§XF‘ÿ*ªebruary“1995.˜Correct“sub-Ž¡‘JÂject–UUheader“mighš¸ãt“bGe“di eren˜t.ަ‘63×[62]ŽŽ‘JÂMarc–¹v‘ÿqÇan“Leeu•¸ãw“en.‘ˆ¯On›¹in“terpretation˜of˜la“y“out˜features.‘ˆ¯P“osting˜inŽ¡‘JÂÈcomp.programming.literate²,–UUF‘ÿ*ªebruary“1995.‘nïCorrect“sub‘Ž8ject“wš¸ãas“di eren˜t.ަ‘63×[63]ŽŽ‘JÂMarc–„èv‘ÿqÇan“Leeu•¸ãw“en.› í^Alignmen“t–„èof“assignmen¸ãts“in“ÈCWEAVE².˜P¸ãosting“inŽ¡‘JÂÈcomp.programming.literate²,‘½^Marcš¸ãh–¨1996.‘fôCorrect“sub‘Ž8ject“header“migh˜t“bGeŽ¡‘JÂdi erenš¸ãt–UU(date“and“n˜um˜bGer“here:‘qÇ2986,“19“Mar“1996.ަ‘63×[64]ŽŽ‘JÂMarc–x-v‘ÿqÇan“Leeu•¸ãw“en.‘ѧPrett“yprin“ting–x-in“no•¸ãw“eb›x-(w“as:‘·vthe˜underscore˜dilema).Ž¡‘JÂP¸ãosting–UUin“Ècomp.programming.literate²,“April“1996.ަ‘63×[65]ŽŽ‘JÂR.–ìÌW‘ÿ*ªaters.‘2NUser“format“conš¸ãtrol“in“a“LISP‘ì¥prett˜yprin˜ter.‘2NÎA¾“CM‘T‘ÿ;¼r‘ÿ}'ansactionsŽ¡‘JÂon›“çPr–ÿ}'o“gr“amming˜L“anguages˜and˜Systems²,–UU5(4):513{531,“OctobGer“1983.ަ‘63×[66]ŽŽ‘JÂR.C.–mtW‘ÿ*ªaters.‘¶ÑUsing“the“new“common“LISP‘mnprettš¸ãy“prin˜ter.‘¶ÑÎLisp–ªand“Symb‘ÿ}'olicŽ¡‘JÂComputation²,–UUV(2):27{34,“April{June“1992.ަ‘63×[67]ŽŽ‘JÂK.–ΉWinš¸ãter“and“C.“Co•Gok.‘“5A‘Îgprotot˜yp“e–Ήin˜telligen˜t“prett˜yprin˜ter“for“P˜ascal.‘“5ÎA¾“CMŽ¡‘JÂSIGPLAN‘“çNotic‘ÿ}'es²,–UU24(9):116{125,“Septem¸ãbGer“1989.ަ‘63×[68]ŽŽ‘JÂM.‘ƒrW›ÿ*ªo•Go“dman.‘ó=F˜ormatted–ƒrsyn¸ãtaxes“and“MoGdula-2.‘ó=ÎSoftwar›ÿ}'e–©Ù|“Pr˜actic˜e“&Ž¡‘JÂExp–ÿ}'erienc“e²,–UU16(7):605{626,“July“1986.ަ‘63×[69]ŽŽ‘JÂA.–5ýY‘ÿ*ªehš¸ãudai.‘ jAutomatic“inden˜tation“v˜ersus“program“formatting.‘ jÎA¾“CM‘baSIG-Ž¡‘JÂPLAN‘“çNotic‘ÿ}'es²,–UU15(10):85{87,“1980.ŽŽŽŒ‹=9– ½\È ýN£8 ˜G ýÑGŸì‘'¿¬ÅIndexŽŽ .¸å ýïG‘'¿¬È/*².–ªª.“.“È*/–UU²commen¸ãts,“47ޤ é‘'¿¬È//–UU²commen¸ãts,“47Ž¡‘'¿¬[,–UUcoGde“delimiters,“23Ž¡‘'¿¬2.0,‘UU6Ž©N‘'¿¬A¸ãCM,‘UU40Ž¡‘'¿¬Ada,‘UU39Ž¡‘'¿¬\adaptiv•¸ãe›UUcom“bs",˜45Ž¡‘'¿¬adding–UUcoGde,“23Ž¡‘'¿¬Additional–UUspacing,“41Ž¡‘'¿¬AIX,‘UU6Ž¡‘'¿¬ÇAlgol²,–UU39,“40Ž¡‘'¿¬Algorithm-pGolicy–UUdistinction,“41Ž¡‘'¿¬ASCIGI,‘UU33Ž¡‘'¿¬Assem•¸ãbler›UUlik“e˜command˜set,˜44Ž¡‘'¿¬attac•¸ãhmen“ts,‘UU13Ž¡‘'¿¬Èattr.nw²,‘UU23Ž¡‘'¿¬A¸ãttribute–UUclass,“23Ž¡‘'¿¬attribute–UUde nitions,“11Ž¡‘'¿¬attributes,‘UU13Ž¡‘'¿¬Automatic–UUt¸ãypGesetting,“39Ž¡‘'¿¬a¸ãv‘ÿqÇailable–UUgrammars,“19ަ‘'¿¬Bac¸ãk–UUend,“42Ž¡‘'¿¬bac¸ãkup,‘UU15Ž¡‘'¿¬Îb‘ÿ}'ackupŽ‘EAì²,–UU15,“45Ž¡‘'¿¬Basic–UUactions“of“prett•¸ãyprin“ters,‘UU41Ž¡‘'¿¬Beaut¸ãy‘ÿ*ª,‘UU40Ž¡‘'¿¬Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘Mɲ,–UU15,“44Ž¡‘'¿¬Bison,–UU6,“11,“18,“32,“50Ž¡‘'¿¬Blasc¸ãhek,–UUG.,“42,“46Ž¡‘'¿¬b•Go“oks,‘UU18Ž¡‘'¿¬breakspace,‘UU14Ž¡‘'¿¬Îbuild‘‰ffŽ‘®pp‘ÿ}'arseŽ‘\›ˆ²,‘UU48ަ‘'¿¬C,–UU17,“19Ž¡‘'¿¬ÇC²,–UU16,“45,“53Ž¡‘'¿¬C–UUcoGde“in“rules,“23Ž¡‘'¿¬ÇC–UU²preproGcessor,“16Ž¡‘'¿¬ÇCŸÿ²++Ž‘Ž<,–UU16,“45,“49,“54Ž¡‘'¿¬Îc–ÿ}'anc“elŽ‘BÙ8²,–UU16,“45Ž¡‘'¿¬\case"–UUconstruct,“41Ž¡‘'¿¬c¸ãhristmas–UU1996,“6Ž¡‘'¿¬Classes–UUof“commen¸ãts,“46Ž¡‘'¿¬coGde–UUdelimiters,“23ŽŽŽ ýïG’íìzcoGde–UUin“attributesޤ ®’ìzsummary‘ÿ*ª,‘UU25Ž¡’íìzcolon,‘UU11Ž¡’íìzcom¸ãbining–UUrules,“11Ž¡’íìzCommand‘UUsetŽ¡’ìzassem•¸ãbler›UUlik“e,˜44Ž¡’ìzcon•¸ãv“enien“t,‘UU45Ž¡’ìzsuciency‘ÿ*ª,‘UU43Ž¡’ìzsucien¸ãt,‘UU45Ž¡’íìzCommen¸ãts,‘UU46Ž¡’ìzin–UUPretzel“input“ les,“54Ž¡’íìzComm¸ãunication–UUprotoGcol,“41Ž¡’íìzÈcomp.programming.literate²,‘UU6Ž¡’íìzCompilersŽ¡’ìzand›UUprett•¸ãyprin“ters,˜40Ž¡’ìzfor–UUdoGcumen¸ãts,“40Ž¡’íìzcompilers,‘UU18Ž¡’íìzcomplex–UUlanguages,“16Ž¡’íìzcomplex–UUtok¸ãens,“11Ž¡’íìzConnector–UUlines,“41Ž¡’íìzCon¸ãtext–UUfree“grammar,“44,“52Ž¡’íìzcon¸ãtext–UUfree“grammar,“11Ž¡’íìzcon¸ãtext–UUfree“grammars,“18Ž¡’íìzCon•¸ãtext›UUsensitiv“e˜formatting,˜46Ž¡’íìzcon•¸ãtext›UUsensitiv“e˜grammars,˜18,˜21Ž¡’íìzCon¸ãtrol–UUsequences,“40Ž¡’íìzcon¸ãtrol–UUsequences,“13Ž¡’íìzcon•¸ãtrolling›UUinden“tation,˜13Ž¡’íìzcon¸ãtrolling–UUline“breaks,“14Ž¡’íìzCon•¸ãv“enien“t–UUcommand“set,“45Ž¡’íìzCon•¸ãv“en“tions,‘UU50Ž¡’íìzCoGok,–UUC.,“46Ž¡’íìzCop•¸ãy›UUcommen“ts,˜47Ž¡’íìzCoroutines,‘UU41Ž¡’íìzcreate,‘UU24Ž¡’íìzCWEB,‘UU7ŽŸÎW’íìzÈ-d–UU²option“of“Bison,“30Ž¡’íìzÈ-d–UU²option“of“Èpretzel-it²,“20,“28Ž¡’íìzDarmstadt,‘UU6Ž¡’íìzdateŽ¡’ìzup–UUto,“6Ž¡’íìzdebug–UUo “function,“28Ž¡’íìzdebug–UUon“function,“28Ž¡’íìzdebug–UUprin¸ãt,“26ŽŽŽŽŽŽŸK’×lx61ŽŽŒ‹>F) ½\È ýN£8‘63ײ62’>KZÃINDEXŽŽ ˜G ý„‘63ײdebugging–UUgrammars,“19ޤ J‘63×debugging–UUmoGde,“20Ž¡‘63×De ating›8ãprett•¸ãyprin“ting˜grammars,‘qÇ45Ž¡‘63×DoGcumen¸ãt–UUcompilers,“40Ž¡‘63×doGcumen•¸ãts,›UUo“wn,˜9Ž¡‘63×Dublin,‘UU6Ž¡‘63×Dv¸ãorak,–UUJan,“40Ž©Ù‘63×Early›UUprett•¸ãyprin“ters,˜41Ž¡‘63×EditorsŽ¡‘J3×syn¸ãtax–UUdirected,“42Ž¡‘63×Empt•¸ãy›UUtok“ens,˜47Ž¡‘63×ending–UUcoGde,“25Ž¡‘63×Equalit¸ãy‘ÿ*ª,‘UU46Ž¡‘63×error–UUtok¸ãen,“20Ž¡‘63×escapGed–UUunderlines,“24Ž¡‘63×ev•¸ãeryda“y–UUsetting,“7Ž¡‘63×Èexample-frame.tex²,‘UU9Ž¡‘63×Exceptions,‘UU16Ž¡‘63×executable›UUprett•¸ãyprin“ter,˜9Ž¡‘63×expGectations,‘UU9Ž¡‘63×Explicit–UUformat“commands,“42ަ‘63×È.fg–UU²sux,“50,“55Ž¡‘63×FIF¸ãO–UUbu er,“41Ž¡‘63×File–UUformats,“50Ž¡‘63×Filename›UUcon•¸ãv“en“tions,˜50Ž¡‘63× ex,–UU6,“11,“32,“50Ž¡‘63× exdoGc,–UU11,“32Ž¡‘63×Flexibilit¸ãy‘ÿ*ª,‘UU16Ž¡‘63×F‘ÿ*ªolding,–UU41,“43Ž¡‘63×F›ÿ*ªolding–¾¼algorithm“(Rose“and“W˜elsh),ŽŸ ‘^3×42Ž¡‘63×force,‘UU13Ž¡‘63×formal–UUlanguage“theory‘ÿ*ª,“18Ž¡‘63×F‘ÿ*ªormal–UUmethoGds,“42Ž¡‘63×F‘ÿ*ªormat–UUcommands,“41Ž¡‘J3×Îb‘ÿ}'ackupŽ‘g¶²,–UU15,“45Ž¡‘J3×Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘oxô²,–UU15,“44Ž¡‘J3×Îc–ÿ}'anc“elŽ‘eMc²,–UU16,“45Ž¡‘J3×explained,‘UU16Ž¡‘J3×explicit,‘UU42Ž¡‘J3×implicit,‘UU42Ž¡‘J3×Îno‘‰ffŽ‘®indentŽ‘t蜲,–UU16,“45Ž¡‘J3×Înul‘‚ØlŽ‘[ØÌ²,‘UU16Ž¡‘J3×summary‘ÿ*ª,‘UU16Ž¡‘63×format‘UUcommandsŽ¡‘J3×additional,‘UU15Ž¡‘J3×bac¸ãkup,‘UU15Ž¡‘J3×breakspace,‘UU14Ž¡‘J3×opt,‘UU15Ž¡‘63×F‘ÿ*ªormatted–UUgrammar“ le,“50,“52Ž¡‘63×formatted–UUgrammar“ le,“10,“11Ž¡‘63×F‘ÿ*ªormatted–UUtok¸ãen“ le,“50,“51ŽŽŽ ý„’ü`¥formatted–UUtok¸ãen“ le,“10ޤ ’`¥placemen¸ãt–ë[of“regular“expressions,ŽŸ ’$`¥11Ž¡’ü`¥formatting,‘UU13Ž¡’ü`¥F‘ÿ*ªormatting–UUalgorithm,“41Ž¡’ü`¥F‘ÿ*ªormatting–UUalgorithms,“39Ž¡’ü`¥formatting–UUinstructions,“12,“13Ž¡’ü`¥F–ÿ*ªormatting›UUpGolicy“,˜41,˜43Ž¡’ü`¥F‘ÿ*ªormatting–UUstandards,“39Ž¡’ü`¥\free–UUformat"“languages,“39Ž¡’ü`¥F‘ÿ*ªree›UUSoft•¸ãw“are˜F‘ÿ*ªoundation,˜6Ž¡’ü`¥F‘ÿ*ªron¸ãt–UUend,“42Ž¡’ü`¥È.ft–UU²sux,“50,“55Ž©>P’ü`¥G‘úÿÿartner,–UUF‘ÿ*ªelix,“19Ž¡’ü`¥GNU–UUÈg++“²Compiler,“6Ž¡’ü`¥GNU–UUGeneral“Public“License,“6Ž¡’ü`¥go•Go“d–UUnews,“19Ž¡’ü`¥grammar–UUrules,“13Ž¡’ü`¥grammar,–UUcon¸ãtext“free,“11Ž¡’ü`¥grammarsŽ¡’`¥prett•¸ãyprin“ting,‘UU16Ž¡’ü`¥Grogono,–UUP‘ÿ*ª.,“46Ž¡’ü`¥Guidelines–UU(Rose“and“W‘ÿ*ªelsh),“42ަ’ü`¥handling–UUiden¸ãti ers,“10Ž¡’ü`¥Hearn,–UUA.“C.,“41,“42Ž¡’ü`¥History–UUof“prett•¸ãyprin“ting,‘UU40Ž¡’ü`¥Hmmm,‘UU18Ž¡’ü`¥homepageŽ¡’`¥Pretzel,–UU6,“17Ž¡’ü`¥Horizon¸ãtal–UUspacing,“46Ž¡’ü`¥HP-UX,‘UU6Ž¡’ü`¥HTML,‘UU32Ž¡’ü`¥h¸ãum,–UUrattle“and,“9ަ’ü`¥Implicit–UUformat“commands,“42Ž¡’ü`¥In-text–UUproGcedural“markup,“40Ž¡’ü`¥Include–UU les“for“grammars,“48Ž¡’ü`¥inden¸ãt,‘UU13Ž¡’ü`¥Inden¸ãtation,‘UU41Ž¡’ü`¥inden¸ãtation,‘UU13Ž¡’ü`¥Inden•¸ãting‘æFprograms,‘ ‚Îse‘ÿ}'e‘¦¡²Prett“yprin“t-ŽŸ ’$`¥ersŽ¡’ü`¥indexing,–UUautomatic,“7Ž¡’ü`¥Inituitiv¸ãe–UUgrammar“format,“48Ž¡’ü`¥install,‘UU24Ž¡’ü`¥installing–UUPretzel,“6Ž¡’ü`¥In•¸ãtelligen“t›UUprett“yprin“ter,˜46Ž¡’ü`¥ITI,‘UU6ަ’ü`¥Jac•¸ãk“el,–UUM.,“46Ž¡’ü`¥Ja¸ãv‘ÿqÇa,–UU17,“19Ž¡’ü`¥join,‘UU24ŽŽŽŽŽŽŒ‹?Q[ ½\È ýN£8‘'¿¬ÃINDEX’>KZ²63ŽŽ ˜G ý„‘'¿¬Kaelbling,–UUM.“J.,“46ޤ ¬‘'¿¬Kehr,–UURoger,“6Ž¡‘'¿¬Kellington,–UUMyrtle,“40Ž¡‘'¿¬Kien¸ãtzle,–UUTim,“7Ž¡‘'¿¬Kloso¸ãwski,–UUPrzemek,“36Ž¡‘'¿¬Kn¸ãuth,–UUDonald“E.,“35,“40{42,“44Ž¡‘;¿¬command–UUset“b¸ãy‘ÿ*ª,“40ŽŸå‘'¿¬È.l–UU²sux,“55Ž¡‘'¿¬Language–UU(in)depGendence,“42Ž¡‘'¿¬language–UUde nition“grammars,“18Ž¡‘'¿¬Language–UUdepGendenš¸ãt“fron˜t“end,“42Ž¡‘'¿¬Language–-¨indepGendenš¸ãt“bac˜k“end,‘c½42,Ž© ‘O¿¬43Ž¡‘'¿¬Èlanguages/examples²,‘UU7Ž¡‘'¿¬LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX,–UU9,“32Ž¡‘'¿¬Latex–UUcw¸ãeb“output,“26Ž¡‘'¿¬Ledgard,–UUHenry“F.,“39Ž¡‘'¿¬v‘ÿqÇan‘ŽvLeeuv¸ãen,–œ¿Marc,“5,“16,“20,“32,“40,ަ‘O¿¬45,‘UU47Ž¡‘'¿¬Levy‘ÿ*ª,–UUSilvio,“41Ž¡‘'¿¬Lexical–UUlev¸ãel,“44Ž¡‘'¿¬line–UUbreaks,“14Ž¡‘'¿¬Link¸ãed–UUfolds,“46Ž¡‘'¿¬ÇLisp²,–UU39,“41Ž¡‘'¿¬literate–UUprogramming,“35Ž¡‘'¿¬loGokup–UUtable,“24Ž©å‘'¿¬Markup,–UU40,“44Ž¡‘'¿¬markup,‘UU13Ž¡‘'¿¬matc¸ãh–UUiput“patterns,“10Ž¡‘'¿¬Mateti,–UUP‘ÿ*ª.,“42Ž¡‘'¿¬McKeeman,–UUWilliam,“40Ž¡‘'¿¬Metasyn¸ãtax–UU(Rose“and“W‘ÿ*ªelsh),“42Ž¡‘'¿¬MoGdula-2,‘UU45Ž¡‘'¿¬MoGdularit¸ãy‘ÿ*ª,‘UU43Ž¡‘'¿¬moGdules,‘UU5Ž¡‘'¿¬Mohilner,–UUP¸ãatricia“R.,“46Ž¡‘'¿¬m¸ãuliple–UUmoGdules,“31ަ‘'¿¬È-n–UU²option“of“Èpretzel-it²,“36Ž¡‘'¿¬naming›UUcon•¸ãv“en“tions,˜38Ž¡‘'¿¬Naur,–UUP¸ãeter,“40Ž¡‘'¿¬Necessary–UUcommand“set,“44Ž¡‘'¿¬Neerac¸ãher,–UUMatthias,“37Ž¡‘'¿¬newlines,‘UU26Ž¡‘'¿¬newsgroup,‘UU6Ž¡‘'¿¬\No",‘UU43Ž¡‘'¿¬Îno‘‰ffŽ‘®indentŽ‘Rtq²,–UU16,“45Ž¡‘'¿¬Norman,–UUA.“C.,“41,“42Ž¡‘'¿¬no•¸ãw“eb,–UU6,“35,“36Ž¡‘;¿¬prett•¸ãyprin“ter–UUAPI,“36Ž¡‘;¿¬problems,‘UU38Ž¡‘'¿¬no•¸ãw“eb.st“y‘ÿ*ª,‘UU38ŽŽŽ ý„’íìzNro ,–UU13,“40ޤ $’íìzÎnul‘‚ØlŽ’ÿ‘o²,‘UU16Ž©Öƒ’íìzOmissions,‘UU47Ž¡’íìzOppGen,–UUDerek“C.,“42Ž¡’íìzopt,‘UU15Ž¡’íìzoutden¸ãt,‘UU13Ž¡’íìzo•¸ãwn›UUdoGcumen“ts,˜9ަ’íìzµP‘c²,‘UU49Ž¡’íìzP¸ãarse–UUtree,“42Ž¡’íìzparser–UUgenerator,“18Ž¡’íìzparsing,‘UU18Ž¡’íìzP¸ãascal,‘UU19Ž¡’íìzÇP‘ÿ ascal²,–UU18,“39{42,“47,“51,“53Ž¡’íìzP¸ãersonal–UUtaste,“39Ž¡’íìzPL/I,–UU39,“41Ž¡’íìzplacing–UUregular“expressions,“11Ž¡’íìzP¸ãolicy-algorithm–UUdistinction,“41Ž¡’íìzPOSIX,‘UU50Ž¡’íìz\pGostcommen¸ãts"–8ã(Rose“and“W‘ÿ*ªelsh),‘qÇ46Ž¡’íìzÈPparse–UU²class,“28Ž¡’íìzÈPPARSE‘¡E‰ff&fŽ‘Ç«NAME–UU²macro,“28,“31Ž¡’íìz\precommen¸ãts"–ü (Rose“and“W‘ÿ*ªelsh),‘ è46Ž¡’íìzPreproGcessing–8ãof“format“commands,‘qÇ16Ž¡’íìzPreproGcessor,‘UU16Ž¡’íìz\preproGcessor"–UUfor“prett•¸ãyprin“ting,‘UU42Ž¡’íìzPrettprin¸ãting–UUscanner,“50Ž¡’íìzprett•¸ãyprin“t–UUfunction,“28Ž¡’íìzPrett•¸ãyprin“terŽ¡’ìz rst,‘UU40Ž¡’ìzin•¸ãtelligen“t,‘UU46Ž¡’íìzprett•¸ãyprin“terŽ¡’ìzexecutable,‘UU9Ž¡’ìzgenerator,‘UU5Ž¡’íìzPrett•¸ãyprin“tersŽ¡’ìzbasic–UUactions,“41Ž¡’ìzearly–UUsystems,“41Ž¡’ìzfor–UUother“languages,“39Ž¡’ìzrunning–UUon“k•¸ãeyw“ords,‘UU41Ž¡’íìzPrett•¸ãyprin“ting,‘UU39Ž¡’ìzhistory‘ÿ*ª,‘UU40Ž¡’ìzlanguage–UU(in)depGendence,“42Ž¡’ìzproblems,‘UU45Ž¡’íìzprett•¸ãyprin“tingŽ¡’ìzgrammars,‘UU16Ž¡’ìzhistory‘ÿ*ª,‘UU12Ž¡’ìzidea,‘UU13Ž¡’ìzmoGdules,‘UU5Ž¡’ìzwith–UUformat“commands,“13Ž¡’íìzPrett•¸ãyprin“ting‘UUgrammarŽ¡’ìzinclude–UU les,“48Ž¡’íìzPrett•¸ãyprin“ting–UUgrammar,“16,“47,“48Ž¡’ìzand–UUcommen¸ãts,“46ŽŽŽŽŽŽŒ‹@^š ½\È ýN£8‘63ײ64’>KZÃINDEXŽŽ ˜G ý„‘J3ײde ating,‘UU45ޤ ®‘63×prett•¸ãyprin“ting–UUgrammar,“11Ž¡‘J3×w•¸ãatc“hing–UUparse,“20Ž¡‘63×prett•¸ãyprin“ting–UUgrammars,“18Ž¡‘J3×a¸ãv‘ÿqÇailable,‘UU19Ž¡‘63×prett•¸ãyprin“ting–UUmoGdule,“30Ž¡‘63×Prett•¸ãyprin“ting–UUparser,“50Ž¡‘63×prett•¸ãyprin“ting–UUparser,“27Ž¡‘63×prett•¸ãyprin“ting–UUparser“in¸ãterface,“28Ž¡‘63×Prett•¸ãyprin“ting‘UUproblemsŽ¡‘J3×w¸ãorst–UUand“oldest,“46Ž¡‘63×prett•¸ãyprin“ting–UUscanner,“27Ž¡‘63×prett•¸ãyprin“ting–UUscanner“class,“27Ž¡‘63×PretzelŽ¡‘J3×currect–UUrelease,“6Ž¡‘J3×example–UUoutput,“9Ž¡‘J3× le–UUextensions,“7Ž¡‘J3×history‘ÿ*ª,‘UU6Ž¡‘J3×homepage,–UU6,“17Ž¡‘J3×input–UU les,“7,“10Ž¡‘J3×installing,‘UU6Ž¡‘J3×in¸ãterface,‘UU26Ž¡‘J3×output,‘UU9Ž¡‘J3×prett•¸ãyprin“ting–UUmethoGd,“10Ž¡‘63×Pretzel,‘UU47Ž¡‘J3×concept,‘UU49Ž¡‘J3×options,‘UU55Ž¡‘63×PretzelŽ¡‘J3×obtaining,‘UU6Ž¡‘J3×ultimate–UUsource,“5Ž¡‘63×ÈPRETZEL‘¡E‰ff&fŽ‘Ç«INCLUDE‘8›²en•¸ãvironmen“t‘8ãv‘ÿqÇariable,Ž© ‘^3×30Ž¡‘63×Èpretzel-it²,‘UU9Ž¡‘J3×option–UUÈ-d²,“20Ž¡‘63×ProGcedural–UUmarkup,“40,“44Ž¡‘63×Program–UUformatting,“39Ž¡‘63×Pscan–UUclass,“27Ž¡‘63×ÈPscan.h–UU²header“ le,“27Ž¡‘63×ÈPSCAN‘¡E‰ff&fŽ‘Ç«NAME–UU²macro,“27,“30Ž¡‘63×Èptokdefs.h–UU²header“ le,“30ŽŸ‡®‘63×Ramsey‘ÿ*ª,–UUNorman,“6,“35,“36,“39Ž¡‘63×rattle–UUand“h¸ãum,“9Ž¡‘63×ÈREADME²,‘UU6Ž¡‘63×recursion,‘UU11Ž¡‘63×reducing–UUtok¸ãens,“11Ž¡‘63×reference–UUgrammars,“18Ž¡‘63×regular–UUexpressions,“10Ž¡‘J3×placemenš¸ãt–8ãin“formatted“tok˜en“ le,ަ‘^3×11Ž¡‘63×restrictions,‘UU21Ž¡‘63×restrictions–UUof“Pretzel,“19Ž¡‘63×Reuseabilit¸ãy‘ÿ*ª,‘UU43Ž¡‘63×Rigid–UUformatting“rules,“42ŽŽŽ ý„’ü`¥robust–UUgrammars,“20ޤ $’ü`¥Rose,–UUG.“A.,“42{44,“46Ž¡’ü`¥RS6000,‘UU6Ž¡’ü`¥Rubin,–UULisa“F.,“41,“44Ž©Öƒ’ü`¥Sametinger,–UUJ.,“42Ž¡’ü`¥Sc•¸ãhroGd,›UUJoac“him,˜6Ž¡’ü`¥Sc•¸ãh“w“artz,–UUBarry‘ÿ*ª,“21,“38,“49Ž¡’ü`¥\scopGed–UUcommen¸ãts"“(Kaelbling),“46Ž¡’ü`¥scratc¸ãh,‘UU17Ž¡’ü`¥Second–UUclass“citizens,“46Ž¡’ü`¥semicolon,‘UU11Ž¡’ü`¥Separation–UUof“concerns,“42Ž¡’ü`¥setting,›UUev•¸ãeryda“y‘ÿ*ª,˜7Ž¡’ü`¥Èsimpas.ft²,‘UU7Ž¡’ü`¥Èsimpas.fg²,‘UU7Ž¡’ü`¥Èsimpaspp²,‘UU9Ž¡’ü`¥Èsmall-example.tex²,‘UU9Ž¡’ü`¥SpacingŽ¡’`¥additional,‘UU41Ž¡’`¥horizon¸ãtal,‘UU46Ž¡’`¥horzon¸ãtal,‘UU44Ž¡’`¥v¸ãertical,‘UU44Ž¡’ü`¥\spGecial–UUmark¸ãers",“41Ž¡’ü`¥SPIDER,‘UU18Ž¡’ü`¥standard–UUinput,“9Ž¡’ü`¥standard–UUoutput,“9Ž¡’ü`¥starting–UUcoGde,“25Ž¡’ü`¥State–UUof“the“art,“42Ž¡’ü`¥studen¸ãts,‘UU6Ž¡’ü`¥Suciency–UUof“command“set,“43Ž¡’ü`¥Sucien¸ãt–UUcommand“set,“45Ž¡’ü`¥Summary–UUof“format“commands,“16Ž¡’ü`¥sym¸ãbGolic–UUnames,“10Ž¡’ü`¥syn¸ãtax–UUerror,“20Ž¡’ü`¥Syn¸ãtax-directed–UUeditors,“42ަ’ü`¥T‘ÿ*ªags,‘UU40Ž¡’ü`¥tags,‘UU13Ž¡’ü`¥T‘ÿ*ªasteŽ¡’`¥pGersonal,‘UU39Ž¡’ü`¥T‘þU>Ÿ'EŽ‘ãxX,–UU13,“39,“40,“43Ž¡’ü`¥text–UUformatter,“13Ž¡’ü`¥tips–UUand“tric¸ãks,“26Ž¡’ü`¥È%token–UU²declarations,“11Ž¡’ü`¥È%token–UU²de nitions,“47Ž¡’ü`¥tok¸ãen–UUheader“ le,“30Ž¡’ü`¥tok¸ãens,–UU10,“11Ž¡’`¥sym¸ãbGolic–UUnames,“10Ž¡’ü`¥T‘ÿ*ªoGoth,‘UU46Ž¡’ü`¥T‘ÿ*ªradition,‘UU40Ž¡’ü`¥T‘ÿ*ªric¸ãky–UUdetails,“16Ž¡’ü`¥T‘ÿ*ªrinit¸ãy–UUCollege,“Dublin,“6Ž¡’ü`¥T‘ÿ*ªro ,–UU13,“40ŽŽŽŽŽŽŒ‹Al  ½\È ýN£8‘'¿¬ÃINDEX’>KZ²65ŽŽ ˜G ý„‘'¿¬T¸ãypGesetters,‘UU39ޤ ‘'¿¬T¸ãypGesetting–UUsystems,“39Ž¡‘'¿¬T•¸ãypGesetting›UUcommen“ts,˜46Ž©‘'¿¬ultimate–UUsource,“5Ž¡‘'¿¬UNIX,–UU6,“13,“18Ž¡‘'¿¬ÇUNIX²,‘UU40Ž¡‘'¿¬USENET,‘UU6Ž¡‘'¿¬User–UUcon¸ãtrol,“45Ž¡‘'¿¬user‘UUcon¸ãtrolŽ¡‘;¿¬full,‘UU5Ž¡‘'¿¬using–UUPretzel“output,“9ަ‘'¿¬v¸ãertical–UUline,“11ަ‘'¿¬W‘ÿ*ªaldsc•¸ãhmidt,›UUHelm“ut,˜6Ž¡‘'¿¬w•¸ãatc“hing–UUthe“parse,“20Ž¡‘'¿¬ÈWEAVE²,‘UU40Ž¡‘'¿¬WEB,‘UU18Ž¡‘'¿¬ÈWEB²,‘UU43Ž¡‘'¿¬W‘ÿ*ªelsh,–UUJ.,“42{44,“46Ž¡‘'¿¬Win¸ãter,–UUK.,“46Ž¡‘'¿¬Witten¸ãbGerg,–UULee,“6,“19Ž¡‘'¿¬W‘ÿ*ªo•Go“dman,–UUM.,“42,“45Ž¡‘'¿¬writing–UUgrammars,“17ަ‘'¿¬È.y–UU²sux,“55Ž¡‘'¿¬Y‘ÿ*ªeh¸ãudai,–UUA.,“45Ž¡‘'¿¬yytext,‘UU24ŽŽŽŽŽŽŒøyQƒ’À;è½\ÈŸp Aó1߆µT cmtt12ó0߆µTáH cmtt12ó/¡8)Ïcmsl8ó.Œ-ø cmcsc10ó-߆µTff cmtt12ó*Œ-øff cmcsc10ó)#Ñfcmti8ó%Œ-ø cmcsc10ó$ßCÊscmtt8ó#ý': cmti10ó"ÂÖN  cmbx12ó!ÂÖN ff cmbx12óÂÖN ½q cmbx12óßê cmmi10óKñ`y cmr10óÙ“ Rcmr7ó†›Zcmr5óäO£ linew10óäO£ line10ù|ßßßßßßßpretzel-2.0n-2/doc/pretzelbook/example-frame.tex0000777000000000000000000000000010765020754030107 2../../languages/examples/example-frame.texustar rootrootpretzel-2.0n-2/doc/pretzelbook/index.list0000644000000000000000000000113406360721351017166 0ustar rootrootthis directory & The PretzelBook Makefile & The Makefile example-frame.tex & frame to view the small example in small-example.tex pretzelbook-1st-ed.dvi & 1st Edition of the PretzelBook (Dec 16 1996) pretzelbook.dvi & second edition of the PretzelBook (Jul 9 1997) pretzelbook.tex & LaTeX source of PretzelBook simpas.fg & small example of formatted grammar file (link) simpas.ft & small example of formatted token file (link) small-example.simpas & Example in simple PASCAL small-example.tex & result from prettyprinting small-example.simpas with the prettyprinter specified in simpas.ft and simpas.fg pretzel-2.0n-2/doc/pretzelbook/small-example.simpas0000777000000000000000000000000010765020754031333 2../../languages/examples/small-example.simpasustar rootrootpretzel-2.0n-2/doc/pretzelbook/index.html0000644000000000000000000000313606360721356017170 0ustar rootroot Index file for directory "pretzel/doc/pretzelbook" of Pretzel distribution

Index file for directory "pretzel/doc/pretzelbook" of Pretzel distribution

Files and directories are:

this directory

    The PretzelBook
Makefile
    The Makefile
example-frame.tex
    frame to view the small example in small-example.tex
pretzelbook-1st-ed.dvi
    1st Edition of the PretzelBook (Dec 16 1996)
pretzelbook.dvi
    second edition of the PretzelBook (Jul 9 1997)
pretzelbook.tex
    LaTeX source of PretzelBook
simpas.fg
    small example of formatted grammar file (link)
simpas.ft
    small example of formatted token file (link)
small-example.simpas
    Example in simple PASCAL
small-example.tex
    result from prettyprinting small-example.simpas with the prettyprinter specified in simpas.ft and simpas.fg

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 16:40:47 MESZ 1997 pretzel-2.0n-2/doc/pretzelbook/small-example.tex0000644000000000000000000000035306255206636020456 0ustar rootrootif $a=1$ then \pretzelindent{}$b:=1$\pretzeloutdent{};\pretzelforce{}if $a<=1$ then\pretzelindent{}\pretzelforce{}begin $b:=2$ end\pretzeloutdent{}\pretzelforce{}else\pretzelindent{}\pretzelforce{}$b:=a$\pretzeloutdent{}\pretzelforce{}pretzel-2.0n-2/doc/pretzelbook/Makefile0000644000000000000000000000137206537751644016644 0ustar rootroot# # $Id$ # # Makefile for the Pretzelbook # # $Log$ # # # where to copy any latex styles to: #TEXINPUTSDIR = /users/gaertner/tex/inputs # LATEX = latex BIBTEX = bibtex MAKEINDEX = makeindex # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ pretzelbook: $(LATEX) pretzelbook.tex $(MAKEINDEX) pretzelbook $(BIBTEX) pretzelbook $(LATEX) pretzelbook.tex $(LATEX) pretzelbook.tex # ------------------------------------------------------------------------ clean: rm -f *.toc *.log *.aux *.idx *.ilg *.bbl *.blg *.ind clobber: clean rm -f *.dvi #bundle: # tar cf $(DISTNAME).tar $(REPFILES) $(MANFILES) $(BOTHFILES) \ # $(DISTFILES) release: pretzel-2.0n-2/doc/pretzelbook/pretzelbook.dvi0000644000000000000000000071243006537752203020244 0ustar rootroot÷ƒ’À;è TeX output 1998.06.11:1458‹ÿÿÿÿ ½\È ýN£8 ˜G þgª©’¡äŸóDÓítG®G®cmr17¹The‘7tPretzelBosŽokŽŸ’½HçóKñ`y cmr10²second‘UUeditionŽŸ,’¹Þ„óX«Q cmr12ºF‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸ’¹ñJune–ê¨11,“1998ŽŽŽŒ‹* ½\È ýN£8‘63ײ2ŽŽ ˜GŽŒ‹1 ½\È ýN£8 ˜G ýÔâ‘'¿¬óÂÖN áH cmbx12ÅCon–ÿ8õten“tsŽŸ>;Å‘'¿¬óò"V cmbx10Æ1Ž‘6¿­In®9troQÇduction’2“5ŽŽ¤ #Ü‘6¿­²1.1Ž‘M¿±Do›UUPrett•¸ãyprin“ting˜the˜Pretzel˜W‘ÿ*ªa“y‘¸‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é5ŽŽ¡‘6¿­1.2Ž‘M¿±History‘x‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é6ŽŽ¡‘6¿­1.3Ž‘M¿±Ac•¸ãkno“wledgemen“ts‘ã ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é6ŽŽ¡‘6¿­1.4Ž‘M¿±Changes–UUto“second“Edition‘¢æ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é6ŽŽ©;Å‘'¿¬Æ2Ž‘6¿­Using‘ÕTPretzel’":7ŽŽ¡‘6¿­²2.1Ž‘M¿±Getting‘UUStarted‘榑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é7ŽŽ¡‘M¿±2.1.1Ž‘m¿²A–UU rst“ExampleTÀ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é7ŽŽ¡‘M¿±2.1.2Ž‘m¿²Running‘UUPretzel‘[Ö‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é9ŽŽ¡‘M¿±2.1.3Ž‘m¿²Using–UUPretzel“Output‘¸.‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é9ŽŽ¡‘6¿­2.2Ž‘M¿±Carrying‘UUOn‘Æ®‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.1Ž‘m¿²The–UUTw¸ão“Input“Files‘MŽ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.2Ž‘m¿²F–ÿ*ªormatted‘UUT“ok¸ãens‘*‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.3Ž‘m¿²Regular‘UUExpressions‘Æp‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é10ŽŽ¡‘M¿±2.2.4Ž‘m¿²F‘ÿ*ªormatted‘UUGrammar‘퉑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é11ŽŽ¡‘M¿±2.2.5Ž‘m¿²Prett•¸ãyprin“ting–UUwith“F‘ÿ*ªormat“Instructions‘ÔI‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é12ŽŽ¡‘M¿±2.2.6Ž‘m¿²F‘ÿ*ªormatting‘UUInstructions‘iê‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é13ŽŽ¡‘6¿­2.3Ž‘M¿±W‘ÿ*ªriting›UUPrett•¸ãyprin“ting˜Grammars‘me‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é16ŽŽ¡‘M¿±2.3.1Ž‘m¿²MoGdifying–UUan“existing“grammar‘Ôo‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é17ŽŽ¡‘M¿±2.3.2Ž‘m¿²W‘ÿ*ªriting–UUa“new“Grammar“from“Scratc¸ãh‘­8‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é17ŽŽ¡‘M¿±2.3.3Ž‘m¿²Conš¸ãtext–UUF‘ÿ*ªree“v˜ersus“Con˜text“Sensitiv˜e‘X‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é18ŽŽ¡‘M¿±2.3.4Ž‘m¿²Av‘ÿqÇailable‘UUGrammars‘&m‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é19ŽŽ¡‘M¿±2.3.5Ž‘m¿²Debugging›UUPrett•¸ãyprin“ting˜Grammars‘& ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é19ŽŽ¡‘M¿±2.3.6Ž‘m¿²ExpGeriences‘¶‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é21ŽŽ¦‘'¿¬Æ3Ž‘6¿­Pretzel‘ÕTHac®9king’þPÔ23ŽŽ¡‘6¿­²3.1Ž‘M¿±Adding–UUóŒ-ø cmcsc10ÇC“²CoGde“to“the“Rules‘Fl‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é23ŽŽ¡‘M¿±3.1.1Ž‘m¿²Example–UUfor“T‘ÿ*ªok¸ãens‘)ý‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é23ŽŽ¡‘M¿±3.1.2Ž‘m¿²Example–UUfor“Grammars‘ÂΑü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é24ŽŽ¡‘M¿±3.1.3Ž‘m¿²Summary‘±I‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é25ŽŽ¡‘M¿±3.1.4Ž‘m¿²Tips–UUand“T‘ÿ*ªric¸ãks‘?n‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é26ŽŽ¡‘6¿­3.2Ž‘M¿±The–UUPretzel“In¸ãterface‘†’‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é26ŽŽ¡‘M¿±3.2.1Ž‘m¿²The›UUPrett•¸ãyprin“ting˜Scanner‘b¿‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é27ŽŽ¡‘M¿±3.2.2Ž‘m¿²The›UUPrett•¸ãyprin“ting˜P“arser‘T‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é28ŽŽ¡‘M¿±3.2.3Ž‘m¿²Example‘±R‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é29ŽŽ¡‘6¿­3.3Ž‘M¿±Building–UUa“Pretzel“prett•¸ãyprin“ter›UUb“y˜Hand‘pÓ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é30ŽŽ¡‘6¿­3.4Ž‘M¿±Obtaining–UUa“Pretzel“Prett•¸ãyprin“ting‘UUMoGdule‘鬑ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é30ŽŽ¡‘M¿±3.4.1Ž‘m¿²The›UUPrett•¸ãyprin“ting˜Scanner‘b¿‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é30ŽŽ¡‘M¿±3.4.2Ž‘m¿²The›UUPrett•¸ãyprin“ting˜P“arser‘T‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é31ŽŽ¡‘6¿­3.5Ž‘M¿±Multiple–UUPretzel“MoGdules“in“the“same“Program‘”J‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é31ŽŽ¡‘6¿­3.6Ž‘M¿±Prett•¸ãyprin“ting–UUfor“non-LŸýó5‘üffóÙ“ Rcmr7±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxXians‘ñ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é32ŽŽŽŸK’Ùìx3ŽŽŒ‹z ½\È ýN£8‘63ײ4’+‹Xóp®0J cmsl10ÃCONTENTSŽŽ ˜G ý„‘\3ܲ3.6.1Ž‘|3ÝOther–UUMarkup“F‘ÿ*ªormatters‘éâ‘ü.ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é32ŽŽ¤ ‘\3Ü3.6.2Ž‘|3ÝGoing–UUfor“ÇHTML;î‘ü².ŽŽ–Ç‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ“‘ü.ŽŽ‘é33ŽŽ©‘63ׯ4Ž‘E3ØPretzel–ÕTmeets“óßêŸ'EŽ‘ãxXŽ¡‘'¿¬to–'6start,‘[®maš¸ãybGe“just“a“sligh˜t“idea“of“what“kind“of“things“regular“expressions“andŽ¡‘'¿¬conš¸ãtext–3îfree“grammars“are,‘:what“prett˜yprin˜ting“is“abGout“and“ho˜w“y˜our“source“coGdeŽ¡‘'¿¬lo•Goks›UUb“est˜in˜a˜prett•¸ãyprin“ted˜w“a“y‘ÿ*ª.ŽŸ"Y.‘'¿¬Ì2.1Ž‘L¦Getting‘ffStartedŽŸYõ‘'¿¬²This–ƒÐsection“will“givš¸ãe“a“ rst“in˜troGduction“to“using“Pretzel.‘ý8It“will“sho˜w“ho˜w“toŽ¡‘'¿¬build–7§a“prett•¸ãyprin“ter–7§for“a“simple“programming“language,‘=–whic¸ãh“will“bGe“a“subset“ofŽ¡‘'¿¬standard–ŽÄÇP‘ÿ ascal².‘After“reading“this“section“and“doing“the“excercises,‘y¸ãou“will“bGeŽ¡‘'¿¬able–û3to“build“arbitrary“prett•¸ãyprin“ters–û3from“the“ready-to-go“input“ les“included“inŽ¡‘'¿¬the–UUPretzel“distibution.ŽŸE ‘'¿¬ó"ÂÖN  cmbx12Í2.1.1Ž‘Pÿ¬A–€ rst“ExampleŽŸè.‘'¿¬²The–Á•input“to“Pretzel“will“alw•¸ãa“ys–Á•bGe“ó#ý': cmti10Îtwo“² les.‘¶‡Let's“start“with“these“ les“ rst“andŽ¡‘'¿¬loGok–tat“Pretzel“in“action.‘&­So“yš¸ãou“migh˜t“startup“y˜our“computer,‘¡in˜v˜ok˜e“y˜our“fa˜v˜ouriteŽ¡‘'¿¬text–Peditor“and“create“t•¸ãw“o–P les“called“Èsimpas.ft“²and“Èsimpas.fg².‘pThe“suxes“È.ftŽ¡‘'¿¬²and–Ù˜È.fg“²are“the“extensions“that“Pretzel“expšGects“for“its“input“ les.‘þBut“b˜efore“w¸ãeŽ¡‘'¿¬learn–UUabGout“what“they“stand“for,“ ll“in“the“ les“with“the“follo¸ãwing“information:Ÿü^ÿ±1ŽŽŽ¦‘'¿¬È/*–?ýsimpas.ft“--“a“simple“pretzel“example“*/Ž¡¡‘'¿¬%%Ž¡¡‘'¿¬";"‘>ÿÜSEMIŽ¡‘'¿¬"="‘>ÿÜ|Ž‘'¿¬Ÿ2’‰ff‰¬Ÿ J=‘ "5Ÿý-:ó¹Aa¨cmr6¼1ŽŽŽ‘LÜó|{Ycmr8»Y‘ÿJªou–QKcan“spare“yšÃŽourself“from“t˜yping“the“data“if“y˜ou“loÿÜ|ޤ ‘63×">"‘>ÿÜ|Ž¡‘63×"<="‘9¿ß|Ž¡‘63×">="‘9¿ß|Ž¡‘63×":="‘9¿ßBINOPŽ¡‘63×"if"‘9¿ßIFŽ¡‘63×"then"‘/?åTHENŽ¡‘63×"else"‘/?åELSEŽ¡‘63×"begin"‘)ÿèBEGŽ¡‘63×"end"‘4âENDŽ¡‘63×[0-9]+‘/?åNUMŽ¡¡‘63×[a-zA-Z][a-zA-Z0-9]*‘ÿôIDŽ¡¡‘63×[\t\–?ý\n]‘$¿ë//“eat“up“whitespaceޤjå‘E3ײHere's–UUthe“second“ le,“whic¸ãh“should“bGe“called“Èsimpas.fg²:Ž¡‘63×È/*–?ýsimpas.fg“--“a“simple“pretzel“example“*/ޤ ¡‘63×%token–?ýSEMI“BINOP“IF“THEN“ELSE“BEG“END“NUM“IDŽ¡¡‘63×%%Ž¡¡‘63×stmt_list–?ý:“stmtŽ¡‘63×|–?ýstmt_list“SEMI“stmt‘$¿ë{“$1“$2“force“$3“}Ž¡‘63×;Ž¡‘63×stmt‘ÿô:–?ýIF“exp“THEN“stmt‘4â{“$1“"“$"“$2“"$“"“$3“"“"“indent“$4Ž¡’ý³eoutdent‘?ý}Ž¡‘`3¿|–?ýIF“exp“THEN“stmt“ELSE“stmtŽ¡’ó3k{–?ý$1“"“$"“$2“"$“"“$3“indent“forceŽ¡’ý³e$4–?ýoutdent“forceŽ¡’ý³e$5–?ýindent“force“$6“outdent“force“}Ž¡¡‘`3¿|–?ýBEG“stmt_list“END‘/?å{“$1“"“"“$2“"“"“$3“}Ž¡‘`3¿|–?ýexp‘?ñ{“"$"“$1“"$"“}Ž¡‘63×;Ž¡‘63×exp‘?ñ:‘?ýIDŽ¡‘`3¿|‘?ýNUMŽ¡‘`3¿|–?ýexp“BINOP“expŽ¡‘63×;Ž©jå‘E3ײThe–ØYlanguage“that“is“co•¸ãv“ered›ØYb“y˜these˜ rst˜Pretzel˜spGeci cations˜is˜ÇP‘ÿ ascal˜²withŽ¡‘63×simple–{‡expressions“of“the“form“ó  b> cmmi10µa–Áó !",š cmsy10¸“µb–{‡²or“µa–Á²=“µb–{‡²(yš¸ãou“can“see“whic˜h“opGerators“are“al-Ž¡‘63×lo•¸ãw“ed–õœfrom“the“Èpascal.ft“² le).‘QßAlso,‘Áthe“only“statemenš¸ãts“allo˜w˜ed“are“assignmen˜ts,Ž¡‘63×the‘ÃlÆifŽ‘ x¿²-ÆthenŽ‘…N²-construct–Ãland“the“compGound“statemenš¸ãt“(i.e.“statemen˜ts“enclosed“withinŽ¡‘63ׯbQÇeginŽ‘T«í²and‘(ÆendŽ‘4‹²).‘bµSo–(the“folloš¸ãwing“(not“prett˜yprin˜ted)“coGde“w˜ould“bGe“v‘ÿqÇalid“in“theseŽ¡‘63×terms:Ÿü^ÿ±2ŽŽŽ¦‘63×Èif–?ýa=1“then“b:=1;Ž¡‘63×if–?ýa<=1“then“begin“b:=2“end“else“b:=aŽ‘63ן /‰ff‰¬Ÿ J=‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»Of–ácourse“yšÃŽou“can't“do“m˜uc˜h“with“this“\language",‘>“but“remem˜band“lea•¸ãv“e–Gºan“executable“called“Èsimpaspp².˜This“ le“is“the“prett•¸ãyprin“terŽ¡‘'¿¬for–UUthe“spGeci ed“language!Ž¡‘6¿¬By–±Zdefault,‘[the“prett•¸ãyprin“ter–±Zreads“text“from“the“standard“input“and“writesŽ¡‘'¿¬formatted–%coGde“to“the“standard“output.‘±6So“try“to“feed“the“small“example“to“theŽ¡‘'¿¬program–UUand“loGok“what“it“returns:ޤΑ'¿¬Èsimpaspp‘?ýŸ'EŽ‘ãxX“coGde“that“yš¸ãou“can“use“within“y˜our“o˜wn“doGcumen˜ts.ŽŸ\€‘'¿¬Í2.1.3Ž‘Pÿ¬Using–€Pretzel“OutputŽŸuT‘'¿¬²There's–fEa“small“doGcumen¸ãt“prepared“to“demonstrate“the“use“of“Pretzel“output“inަ‘'¿¬y•¸ãour›UUo“wn˜doGcumen“ts.‘qÇIt's˜the˜ le˜Èexample-frame.tex².ޤU‘'¿¬È\documentclass{article}ަ‘'¿¬\usepackage{pretzel-latex}ަ‘'¿¬\begin{document}ަ¦‘'¿¬This–?ýis“a“small“example“produced“by“Pretzel“and“formatted“with“\LaTeX{}.ަ¦‘'¿¬\begin{ppcode}ަ‘2?¦\input{small-example.tex}ަ‘'¿¬\end{ppcode}ަ¦‘'¿¬\end{document}Ž¡‘6¿¬²If–‡oyš¸ãou“sa˜v˜e“the“output“of“the“prett˜yprin˜ter“Èsimpaspp“²in“a“ le“b˜y“redirectingަ‘'¿¬the–K¯standard“output“(let's“call“this“ le“Èsmall-example.tex²)“and“run“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“on“theަ‘'¿¬frame,–UUthe“resulting“došGcumen¸ãt“will“lo˜ok“something“lik¸ãe“this:Ž¡‘1¿­if›UUµa–Dz=“1˜then˜µb“²:=“1;ަ‘1¿­if›UUµa–Ç<²=“1˜thenަ‘;¿®bGegin›UUµb–Dz:=“2˜endަ‘1¿­elseަ‘;¿®µb–Dz:=“µaަ¡‘6¿¬²Noš¸ãw–§what“do“y˜ou“think“of“this?‘оIs“it“what“y˜ou“expGected?‘оIt“is“ob˜vious“thatަ‘'¿¬this–;¤is“the“cošGde“that“has“b˜een“input“to“the“prett•¸ãyprin“ter.‘$³But–;¤it“is“not“ob¸ãvious,ަ‘'¿¬hoš¸ãw–Ithe“output“correspGonds“to“the“information“written“do˜wn“in“the“t˜w˜o“input“ lesަ‘'¿¬to–70Pretzel.›YThis“will“bGe“the“sub‘Ž8ject“of“the“next“subsection.˜But,–o§alas,“y•¸ãou‘70ha“v“eަ‘'¿¬w•¸ãork“ed›ïÀy“our˜w“a“y˜through˜this˜ rst˜section˜and˜kno“w˜no“w,‘ho“w˜to˜use˜Pretzel˜in˜it'sަ‘'¿¬simplest‘UUw•¸ãa“y‘ÿ*ª.ŽŽŽŒ‹ sÙ ½\È ýN£8‘63ײ10’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜G ý„‘63×Ì2.2Ž‘[:Carrying‘ffOnŽŸç‘63ײThis–Àsection“will“shoš¸ãw“y˜ou“ho˜w“the“basic“prett˜yprin˜ting“methoGd“w˜orks“that“Pretzelޤ ‘63×uses.‘MŸAfter–óòreading“this“section“y¸ãou“will“bGe“able“to“understand“roughly“what“theŽ¡‘63×con•¸ãten“ts–Àof“Pretzel“input“ les“mean“and“ho¸ãw“to“moGdify“existing“input“ les“to“goŽ¡‘63×with–UUy¸ãour“wishes.Ž©®À‘63×Í2.2.1Ž‘_s×The–€Tw o“Input“FilesŽŸuT‘63ײThe› %prett•¸ãyprin“ting˜methoGd˜used˜b“y˜a˜Pretzel˜prett“yprin“ter˜is˜quite˜simple.‘XbIt˜readsŽ¡‘63×the–ýÕinput,›'ôwhic¸ãh“usually“is“the“plain“source“coGde,˜cuts“this“text“in¸ãto“small“piecesŽ¡‘63×called–¥(Îtokens²,‘¹and“tries“to“rearrange“them“in“suc¸ãh“a“fashion“that“the“user“will“callŽ¡‘63×sthetic.‘˜[Of–b1course,‘¥hthe“relativš¸ãe“order“of“the“input“tok˜ens“will“(usually)“not“bGeŽ¡‘63×cš¸ãhanged,‘=Kbut–çthe“amoun˜t“of“whitespace“in˜bGet˜w˜een“migh˜t“bGe“enlarged“or“reduced,Ž¡‘63×line–eãbreaks“ma¸ãy“bšGe“inserted“at“sp˜ecial“places“etc.‘£rAll“this“is“sp˜eci ed“b¸ãy“rules“thatŽ¡‘63×the–±|user“writes.‘†implemenš¸ãt“a“simple“prett˜yprin˜ter,‘8w˜e“w˜ould“only“need“to“spGecify“the“patternsŽ¡‘63×for–^šthe“tok¸ãens“and“add“some“information,‘`ëwhat“the“output“device“should“do“if“thisŽ¡‘63×pattern–X™can“bGe“matcš¸ãhed.‘{“An“example“will“sho˜w,›™jthat“this“is“not“enough,˜if“y¸ãouŽ¡‘63×strivš¸ãe–UUfor“full“user“con˜trol“o˜v˜er“prett˜yprin˜ting.ަ‘E3×F‘ÿ*ªor–UUexample“lošGok“at“the“follo¸ãwing“ÇP‘ÿ ascal“²co˜de“fragmen¸ãt.ŽŸFÔ‘@3ØÆifŽ‘J>€µi–Ç>“²1‘UUÆthenŽ‘/øµi‘Ž0²:=Ž‘ヵi–8ณ²1;ަ‘@3ØÆifŽ‘J>€µb–Ǹ“µi‘UUÆthenŽŽ¦‘J3Ùµb‘Dz:=Ž‘kµb–8à²+“1ަ‘@3ØÆelseŽ‘UÎ×µb‘Dz:=Ž‘kµb–8ณ²1;ަŸ8©‘E3×Saš¸ãy–é»the“user“w˜an˜ts“the“ rst“statemen˜t“(an“ÆelseŽ‘/e²-less“ÆifŽ‘ Ÿ²)“to“bGe“prett˜yprin˜ted“with-Ž¡‘63×out–zSa“forced“line“break“bGehind“the“ÆthenŽ‘yô²k•¸ãeyw“ord–zSand“the“second“statemen¸ãt“(a“simpleŽ¡‘63ׯifŽ‘<é*²-ÆthenŽ‘…N²-ÆelseŽ‘Eª²)–QÍto“ha•¸ãv“e–QÍa“line“break“bGehind“the“k•¸ãeyw“ords–QÍand“additional“inden¸ãtationŽ¡‘63×to–­âthe“statemenš¸ãts“to“enhance“readabilit˜y‘ÿ*ª.‘9öThis“is“hardly“expressible“in“terms“of“\for-Ž¡‘63×matted–ICtokš¸ãens",‘K­bGecause“it“w˜ould“bGe“necessary“to“go“bac˜k“in“the“output“and“insertŽ¡‘63×a–ƒÙline“break“within“material“that“mighš¸ãt“ha˜v˜e“already“bGeen“output“to“the“screen“orŽ¡‘63×to‘UUpapGer.ަ‘E3×T‘ÿ*ªo–=spGecify“this“distinction“yš¸ãou“ha˜v˜e“to“tell“the“prett˜yprin˜ter“something“abGoutŽ¡‘63×what‘ñÁÆifŽ› §²-ÆthenŽ‘…N²s–ñÁare“in“di erence“to“ÆifŽ˜²-ÆthenŽ‘…N²-ÆelseŽ‘Eª²s.‘P–That's“where“the“formatted“gram-Ž¡‘63×mar–UUcomes“in¸ãto“action.ަ‘E3×If–ùqy¸ãou“lošGok“at“the“Èsimpas.fg“²example“ab˜o•¸ãv“e,‘ Òy“ou'll–ùqnotice“t•¸ãw“o–ùqrules“that“handleŽ¡‘63×these›UUt•¸ãw“o˜di eren“t˜cases.‘qÇHere˜are˜b•Goth˜rules˜again˜to˜lo“ok˜at:ŽŸ8ª‘63×Èstmt‘ÿô:–?ýIF“exp“THEN“stmt‘4â{“$1“"“$"“$2“"$“"“$3“"“"“indent“$4Ž¡’ý³eoutdent‘?ý}Ž¡‘`3¿|–?ýIF“exp“THEN“stmt“ELSE“stmtŽ¡’ó3k{–?ý$1“"“$"“$2“"$“"“$3“indent“forceŽ¡’ý³e$4–?ýoutdent“forceŽ¡’ý³e$5–?ýindent“force“$6“outdent“force“}Ž¡‘63×;ŽŸ8©‘E3ײThe–Ksecond“line“is“more“inš¸ãteresting“at“the“momen˜t:‘lªit“means“that“an˜y“ÈIF‘K²tok˜enŽ¡‘63×follo•¸ãw“ed›½b“y˜Èexp²,–uÈTHEN²,˜Èstmt²,“ÈELSE‘©²and˜Èstmt˜²tok¸ãens˜will˜bGe˜reduced˜again˜to˜a˜ÈstmtŽ¡‘63ײtok•¸ãen.‘ÖÕThe›!¯attac“hed˜description˜in˜curled˜braces˜tells˜the˜prett“yprin“ter˜to˜insertŽ¡‘63×a–åèforced“line“break“(Îfor–ÿ}'c“eŽ‘R̲)“bGehind“the“ÈTHEN‘åòtok¸ãen“if“this“rules“ res.‘#Additionally‘ÿ*ª,Ž¡‘63×the–Xstatemenš¸ãt“follo˜wing“the“ÈTHEN‘Wϲshould“ha˜v˜e“a“little“more“inden˜tation“bGefore“itŽ¡‘63×(ÎindentŽ‘Jú²)–æwhicš¸ãh“should“bGe“tak˜en“bac˜k“afterw˜ards“(ÎoutdentŽ‘!gi²).‘%wThe“same“is“spGeci edŽ¡‘63×for–Jûthe“second“statemenš¸ãt“follo˜wing“the“ÈELSE‘Jø²tok˜en.‘nTWhat“is“done“here“is“to“spGecifyŽŽŽŒ‹ £Ž ½\È ýN£8‘'¿¬Ã2.2.‘ÇCARR‘ÿ*ªYING‘UUON’þV²13ŽŽ ˜G ý„‘'¿¬something–kšlikš¸ãe“an“attac˜hmen˜t“(or“spGecial“attribute)“of“the“tok˜en“whic˜h“this“ruleޤ ‘'¿¬reduces–4bto“(i.e.“the“Èstmt“²tokš¸ãen“on“the“left“hand“side).‘fËThis“attac˜hmen˜t“can“use“theŽ¡‘'¿¬attac•¸ãhmen“ts–Z2of“the“tokš¸ãens“on“the“righ˜t“hand“side“b˜y“referring“to“the“sequence“n˜um˜bGerŽ¡‘'¿¬in–¼ whicš¸ãh“they“appGear“there.‘>¯This“means“that“È$1“²references“the“attac˜hmen˜t“of“the“ÈIFŽ¡‘'¿¬²tokš¸ãen,‘.+È$2–$a²the“attac˜hmen˜t“of“the“Èexp“²tok˜en“and“so“on.‘avAll“the“attac˜hmen˜ts“bGet˜w˜eenŽ¡‘'¿¬the–ùÀcurled“braces“are“put“together“and“form“the“attac•¸ãhmen“t–ùÀof“the“newly“formedŽ¡‘'¿¬tokš¸ãen–ÀK(the“Èstmt“²tok˜en).‘²«Apart“from“referring“to“the“attributes“of“existing“tok˜ens,Ž¡‘'¿¬yš¸ãou–‚Åcan“additionally“insert“spGecial“formatting“instructions“(lik˜e“ÎindentŽ‘Í¿²,‘Ž!ÎoutdentŽ‘(xO²orŽ¡‘'¿¬Îfor–ÿ}'c“eŽ‘=x²)–;fand“strings“(likš¸ãe“the“È"‘?ý$"²)“in˜to“the“sequence“as“\extra"“attac˜hmen˜ts.‘#ûAllŽ¡‘'¿¬these›UUattac•¸ãhmen“ts˜together˜form˜the˜attribute˜of˜the˜new˜Èstmt˜²tok“en.Ž¡‘6¿¬The–M"spšGecial“commands“that“ha•¸ãv“e–M"app˜eared“ab˜o•¸ãv“e,‘NÆe.g.–M"the“ÎindentŽ‘"å>²or“Îfor–ÿ}'c“eŽ‘í²com-Ž¡‘'¿¬mands,‘ókare–ÓÍcalled“Îformat›Ac‘ÿ}'ommands“²or“Îformatting˜instructions².‘í/Subsequen¸ãtly“theŽ¡‘'¿¬prett•¸ãyprin“ting–ˆmethoGd“used“bš¸ãy“Pretzel“prett˜yprin˜ters“is“called“Îpr‘ÿ}'ettyprinting‘2TwithŽ¡‘'¿¬format‘˜Ic‘ÿ}'ommands².‘€The–Zmain“assumption“is“that“wš¸ãe“ha˜v˜e“a“text“formatter“at“handŽ¡‘'¿¬that–Óµuses“Îc–ÿ}'ontr“ol‘+se“quenc“es–Óµ²(or“Îtags²)“inside“the“actual“text“b•Go“dy–Óµfor“spGecifying“allŽ¡‘'¿¬di eren•¸ãt›ÈŒw“a“ys˜of˜formatting˜(suc“h˜as˜fon“ts,›åYinden“tation,˜spacing,˜alignmen“t).‘ËkAn-Ž¡‘'¿¬other–Ǭterm“for“this“w•¸ãa“y–Ǭof“formatting“is“Îin-text›èpr–ÿ}'o“c“e“dur“al˜markup–Ǭ²and“systemsŽ¡‘'¿¬using– this“tec¸ãhnique“are“commonly“called“Îdo–ÿ}'cument‘<c“ompilersŸü^ÿ±4ŽŽ‘|s².‘•ùThe– idea“bGehindŽ¡‘'¿¬the›ò0prett•¸ãyprin“ting˜methoGd˜presen“ted˜here˜is˜to˜systematically˜insert˜spGecial˜format-Ž¡‘'¿¬ting–8instructions“inš¸ãto“the“source“coGde“whic˜h“are“left“to“a“t˜ypGesetter“to“in˜terpret.Ž¡‘'¿¬The–Çùhistory“bšGehind“this“metho˜d“and“the“details“of“the“algorithm“are“explained“inŽ¡‘'¿¬the–öspGecial“cš¸ãhapter“\On“Prett˜yprin˜ting"“(c˜hapter“5).‘TF‘ÿ*ªrom“no˜w“on,‘Nsimply“thinkŽ¡‘'¿¬of–†formatting“instructions“as“actions“that“will“bšGe“p˜erformed“on“the“t¸ãyp˜eset“outputŽ¡‘'¿¬bšGefore–UUit“app˜ears“on“the“screen“or“on“pap˜er.ŽŸùñ‘'¿¬Í2.2.6Ž‘Pÿ¬F‘þàormatting‘€InstructionsޤuT‘'¿¬²No•¸ãw,›UUw“e'll˜ha“v“e˜a˜loGok˜at˜the˜formatting˜instructions˜that˜Pretzel˜o ers.ŽŸùñ‘'¿¬ÆCon•®9trolling‘ÕTInden“tationŽ¡‘'¿¬²W‘ÿ*ªe›TVha•¸ãv“e˜met˜three˜formatting˜instructions˜already:‘ñHÎindentŽ‘ Consider“for“example“a“long“bloGc˜k“ofŽ¡‘63×statemenš¸ãts–íin“ÇP‘ÿ ascal“²that“con˜tain“extremely“long“names“for“iden˜ti ers“as“in“theŽ¡‘63×follo¸ãwing‘UUexample:ަ‘@3ØÈbegin‘?ýstring_buffer[string_buffer_pointer]:=c;Ž¡‘@3Østring_buffer_pointer:=string_buffer_pointer–?ý+“1;“end;ަ‘63ײW‘ÿ*ªe–don't“w•¸ãan“t–line“breaks“to“appGear“within“idenš¸ãti ers“and“w˜e“don't“w˜an˜t“thingsŽ¡‘63×likš¸ãe–UUthis“to“crop“up“when“prett˜yprin˜ting:ަ‘@3ØÆbQÇeginŽ‘^Ù$Îstring‘‰ffŽ‘®bu erŽ’•p²[Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ‘XÎÖ²]‘Ç:=ŽŽ‘kÎcŽ‘F¸²;‘ª¨Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽŽ¡‘Búð²:=ŽŽ‘PPCÎstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’«Wù²+‘8à1;‘UUÆendŽ‘aÁ²;ަ‘63×Here,‘uÐa–<statemenš¸ãt“is“brok˜en“across“t˜w˜o“lines,‘uÐbut“w˜e“w˜ould“prefer“line“breaks“toŽ¡‘63×ošGccur–HÊonly“b˜et•¸ãw“een›HÊt“w“o˜adjacen“t˜statemen“ts˜(and˜usually˜also˜bGefore˜the˜ÆendŽ‘U6²)˜lik“eŽ¡‘63×in:ަ‘@3ØÆbQÇeginŽ‘^Ù$Îstring‘‰ffŽ‘®bu erŽ’•p²[Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ‘XÎÖ²]‘Ç:=ŽŽ‘kÎcŽ‘F¸²;Ž¡‘@3ØÎstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’›ÉƲ:=ŽŽ’©Îstring‘‰ffŽ–®bu er‘‰ffŽ“p‘ÿ}'ointerŽ’&ϲ+‘8à1;Ž¡‘@3ØÆendŽ‘R@D²;ަ‘63×So–×Éthe“conclusion“is,‘ðåthat“wš¸ãe“ha˜v˜e“to“tell“the“formatter,‘ðåwhere“it“is“pGossible“to“breakŽ¡‘63×a–7zline,‘pif“the“currenš¸ãt“bloGc˜k“of“text“should“exceed“the“righ˜t“margin.‘7This“is“doneŽ¡‘63×with–Ôthe“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ›8®‚²primitiv¸ãe.‘íÉBy“inserting“a“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ˜²amidst“t•¸ãw“o‘Ôstatemen“tsŽ¡‘63×(and–‡úev¸ãen“after“the“ÆbQÇeginŽ‘"_ë²and“bšGefore“the“ÆendŽ‘”f²)“the“ab˜o•¸ãv“e–‡úproblem“cannot“happ˜enŽ¡‘63×anš¸ãy–Ÿemore.‘O÷A‘ŸRÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘8E9²tells“the“t˜ypšGesetter,‘±éto“break“a“line“at“this“p˜oin¸ãt,‘±éif“he“isŽ¡‘63×loGoking–UUfor“a“place“to“break“somewhere“near“it.Ž¡‘E3×But–bevš¸ãen“no˜w,‘¶ùa“single“statemen˜t“migh˜t“bšGe“to˜o“long“to“ t“on¸ãto“one“line.‘/ÌConsiderŽ¡‘63×for–W(example“a“ÆwhileŽ‘±Ê²-loGop“or“an“ÆifŽ‘ {²-statemenš¸ãt“with“a“v˜ery“long“expression“that“go˜v˜ernsŽ¡‘63×it,–UUas“in:ަ‘@3ØÈwhile›?ý(str‘¡E‰ff&fŽ–Ç«buf[str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr]<>c)˜and˜(str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr<=buf‘¡E‰ff&fŽ“size)˜doަ‘63ײInserting‘ËÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘4M²s–ËbšGefore“and“after“the“\Èand²"“w¸ãould“seem“to“b˜e“a“go˜o˜d“solutionŽ¡‘63×to–1Tthis“line-breaking“problem.‘ÃBut“breaking“the“line“after“the“\Èand²",–hSsaš¸ãy‘ÿ*ª,“w˜ouldŽ¡‘63×result‘UUinŽŽŽŒ‹Æ€ ½\È ýN£8‘'¿¬Ã2.2.‘ÇCARR‘ÿ*ªYING‘UUON’þV²15ŽŽ ˜G ý„‘1¿­ÆwhileŽ‘Oo¤²(Îstr‘‰ffŽ‘®bufŽ‘uÚ²[Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘-¿F²]–ǵ<>“ÎcŽ‘ñe²)‘UUÆandŽŽ¤ ‘1¿­²(Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘0†^¸‘ÇÎbuf‘‰ffŽ‘®sizeŽ‘$0²)‘UUÆdoŽŽ©_c‘'¿¬²what–üQof“course“is“inš¸ãtolerable.‘TW‘ÿ*ªe“w˜an˜t“a“long“con˜tin˜uous“line“to“bGe“inden˜ted“a“littleŽ¡‘'¿¬if–QIit“is“brokš¸ãen,‘Rbut“the“amoun˜t“of“inden˜tation“for“the“con˜tin˜uing“line“m˜ust“bGe“moreŽ¡‘'¿¬as–“›the“\normal"“indenš¸ãtation“of“con˜trolled“statemen˜ts“inf“conditionals“for“example.Ž¡‘'¿¬This–¹Ldistinction“visually“separates“adjacenš¸ãt“(and“inden˜ted)“statemen˜ts“from“a“singleŽ¡‘'¿¬statemenš¸ãt–¾that“ lls“t˜w˜o“lines.‘«ñT‘ÿ*ªo“this“e ect,‘Øthe“line“Îhas“²to“bšGe“brok¸ãen“around“this“p˜oin¸ãt.Ÿü^ÿ±5ŽŽ‘ÿö²So“the“ÎoptŽ‘4¯²command“denotes“anŽ¡‘'¿¬optional–úLline“break“with“the“con•¸ãtin“uation–úLline“inden¸ãted“a“little“more“with“respGect“toŽ¡‘'¿¬the–UUnormal“inden¸ãtation.Ž¡‘6¿¬So–UUin“the“example“wš¸ãe“therefore“sa˜y:ަ‘1¿­Èwhile›?ý(str‘¡E‰ff&fŽ–Ç«buf[str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr]<>c)˜and˜Îopt4Ž‘‚ËÈ(str‘¡E‰ff&fŽ“buf‘¡E‰ff&fŽ“ptr<=buf‘¡E‰ff&fŽ“size)˜doŽ¡‘1¿­ÎindentŽ‘SJ¤for–ÿ}'c“eŽ‘mÝmÈbegin‘?ý...Îfor–ÿ}'c“eŽ‘’ÉÈendަ‘'¿¬²depGending–u˜on“whether“wš¸ãe“rather“lik˜ed“a“line“break“bGefore“or“after“the“\Èand²".‘ÒThisŽ¡‘'¿¬wš¸ãould–UUthen“yield“the“correct“w˜a˜y“of“formatting,“as“in:ަ‘1¿­ÆwhileŽ‘Oo¤²(Îstr‘‰ffŽ‘®bufŽ‘uÚ²[Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘-¿F²]–ǵ<>“ÎcŽ‘ñe²)‘UUÆandŽŽ¡‘O¿°²(Îstr‘‰ffŽ–®buf‘‰ffŽ“ptrŽ‘0†^¸‘ÇÎbuf‘‰ffŽ‘®sizeŽ‘$0²)‘UUÆdoŽŽ¡‘;¿®bQÇeginŽ‘W¥².–ªª.“.Ž¡‘;¿®ÆendŽŽ¦‘'¿¬²Note›þkho•¸ãw“ev“er˜that˜a˜Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘9X²is˜alw“a“ys˜a˜bGetter˜place˜to˜break˜a˜line˜than˜anŽ¡‘'¿¬optional–UUline“break“denoted“b¸ãy“ÎoptŽ‘Óˆ².ŽŸÛ£‘'¿¬ÆAdditional‘ÕTCommandsŽŸuT‘'¿¬²The–N-list“of“format“commands“is“not“y¸ãet“complete.‘odThere“are“still“a“few“more“prim-Ž¡‘'¿¬itivš¸ães–L£to“learn,‘Šwbut“they“are“not“as“impGortan˜t“as“the“other“commands“that“w˜ereŽ¡‘'¿¬presenš¸ãted–k‡up“to“this“pGoin˜t.‘´^The“follo˜wing“primitiv˜es“w˜ere“in˜troGduced“to“ac˜hiev˜eŽ¡‘'¿¬bšGetter–UUformatting“results“in“sp˜ecial“situations.Ž¡‘6¿¬The–ŸI rst“one“is“called“Îb‘ÿ}'ackupŽ‘"ÀÒ²and“denotes“a“little“negativš¸ãe“horizon˜tal“space.‘5ThisŽ¡‘'¿¬command–hmš¸ãust“bGe“preceded“b˜y“a“Îfor–ÿ}'c“eŽ‘Y4²,‘2¬bšGecause“it“do˜esn't“makš¸ãe“sense“to“bac˜kupŽ¡‘'¿¬within–ÇÛa“line“if“it's“bšGeginning“has“already“b˜een“output.‘ÉZSo“the“t•¸ãw“o‘ÇÛcommandsŽ¡‘'¿¬\Îfor–ÿ}'c“eŽ‘R̲,‘AÃÎb‘ÿ}'ackupŽ‘!IJ"–zappšGearing“in“a“ro¸ãw“can“b˜e“seen“as“a“short“form“for“the“sequenceŽ¡‘'¿¬\ÎoutdentŽ‘!gi²,‘»Îfor–ÿ}'c“eŽ‘ ã²,‘»ÎindentŽ‘ ²".‘eþThe‘¦½Îb‘ÿ}'ackupŽ‘$Ϻ²command–¦½is“used“in“cases“where“statemen¸ãtsŽ¡‘'¿¬are–Õ“preceded“bš¸ãy“labGels“or“simply“where“a“line“should“stic˜k“out“to“the“left“a“bit“inŽ¡‘'¿¬order–UUto“emphasize“it.Ž¡‘6¿¬The–È­next“additional“command“is“called“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘* ʲ.‘ËÏAs“the“name“implies“thisŽ¡‘'¿¬primitivš¸ãe–-acts“lik˜e“a“Îfor–ÿ}'c“eŽ‘iù²,‘G¢but“on“a“bigger“scale.‘·NÎbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘0˜²not“only“forces“a“lineŽ¡‘'¿¬break;‘ãit–³×also“inserts“a“little“extra“v¸ãertical“space“after“the“break.‘NY‘ÿ*ªou“can“use“theŽ¡‘'¿¬Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘PÔ5²primitivš¸ãe–Ïlto“separate“t˜w˜o“adjacen˜t“lines“that“seman˜tically“do“not“bGelongŽ¡‘'¿¬together,–UUlikš¸ãe“t˜w˜o“function“declarations.Ž¡‘6¿¬If–RWyš¸ãou“are“trying“to“t˜ypGeset“ÇC“²or“ÇCŸÿ²++Ž‘à“programs,‘‘—y˜ou“will“need“a“feature“toŽ¡‘'¿¬t¸ãypšGeset–GGso“called“prepro˜cessor“directiv¸ães.‘mThese“are“commands“b˜eginning“with“a“#Ž¡‘'¿¬that–+can“in uence“the“source“cošGde“b˜efore“compilation.‘c°Normally“these“lines“app˜earŽ¡‘'¿¬bGeginning–ò†at“the“left“margin“so“wš¸ãe“w˜an˜t“a“command“that“can“bGe“used“to“t˜ypGesetŽ‘'¿¬ŸÞ‰ff‰¬Ÿ J=‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»In–mâT‘þ•AŸ¸ãEŽ‘MX“terms“the“digit“ó×2cmmi8¾n“»in“the“name“of“the“ó)#Ñfcmti8ÔoptŽ‘=Ž»command“spšÎfor–ÿ}'c“eŽ‘— ²,‘D>and/or“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘-n ²commands“isŽ¡‘O3Ùreplaced–UUbš¸ãy“a“single“command“(the“maxim˜um“of“the“giv˜en“ones).ŽŸ †‘Bl»2.ŽŽŽ‘O3ÙThe‘r¥Îc–ÿ}'anc“elŽ‘þÖ²command–r¥cancels“an¸ãy“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘3y'²,‘ŸûÎoptŽ‘.²,‘ŸûÎfor–ÿ}'c“eŽ‘el²or“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘**g²commandŽ¡‘O3Ùthat– immediatly“precede“or“folloš¸ãw“it“and“also“cancels“an˜y“Îb‘ÿ}'ackupŽ‘%ŠX²commandŽ¡‘O3Ùthat–UUfollo¸ãws“it.Ž© …‘E3×So–¹ùit“seems“that“the“Îc–ÿ}'anc“elŽ‘"~²command“is“a“command“that“mixes“ev¸ãerything“upŽ¡‘63×again–_after“wš¸ãe“ha˜v˜e“put“ev˜erything“in˜to“a“neat“and“tidy“form!‘žBut“this“only“seemsŽ¡‘63×so.‘äòThe–{¹inš¸ãterpretation“done“b˜y“the“prett˜yprin˜ter“according“to“the“t˜w˜o“rules“statedŽ¡‘63×abšGo•¸ãv“e,‘õcw“as‘Õain“tro˜duced–Õato“b˜e“more“generous“and“more“ exible“with“the“placemen¸ãtŽ¡‘63×of–.®format“primitivš¸ães“in˜to“the“source“coGde.‘dåBecause,›6iafter“all,˜the“format“commandsŽ¡‘63×will–6"not“bGe“inserted“bš¸ãy“hand“(as“the“reader“migh˜t“think“after“viewing“the“examplesŽ¡‘63×giv•¸ãen›¸XabGo“v“e),‘×¾but˜they˜will˜bGe˜inserted˜automatically˜b“y˜the˜prett“yprin“ter˜accordingŽ¡‘63×to–UUthe“prett•¸ãyprin“ting–UUgrammar“that“wš¸ãe“ha˜v˜e“bGeen“in˜trošGduced“to“ab˜o•¸ãv“e.ŽŸb_‘63ׯSummary–ÕTof“F‘ÿ «ormat“CommandsŽŸòC‘63ײT‘ÿ*ªable–ùÒ2.1“shoš¸ãws“a“complete“list“of“all“the“format“command“primitiv˜es“in˜troGducedŽ¡‘63×in–ÂÀthis“part“of“the“b•Go“ok.‘ºThe–ÂÀonly“command“that“wš¸ãasn't“men˜tioned“up“to“no˜w“isŽ¡‘63×the‘$Înul‘‚ØlŽ‘í²primitivš¸ãe–$that“serv˜es“as“a“neutral“(or“empt˜y)“command.‘ÞNo˜w,‘WÅwith“theŽ¡‘63×knoš¸ãwledge–ûØof“all“the“in˜trinsic“and“extrinsiv“features“of“the“prett˜yprin˜ting“methoGdŽ¡‘63×of–¼VPretzel“prett•¸ãyprin“ters,›y“ou–¼Vare“ready“to“read,˜write“or“moGdify“prett•¸ãyprin“tingŽ¡‘63×grammars–·íat“yš¸ãour“will.‘™No˜w,‘Гy˜ou“ha˜v˜e“total“con˜trol“o˜v˜er“the“prett˜yprin˜ting“st˜yle;Ž¡‘63×fully–UUuser“conš¸ãtrolled“prett˜yprin˜ting“is“in“y˜our“grasp.ŽŸ"uí‘63×Ì2.3Ž‘[:W‘þ¦friting›ffPrett•ŒÌyprin“ting˜GrammarsŽŸd ‘O3Ù²\Kno¸ãwing–t‘ÈCWEB‘t‰²and“its“sources,‘|`it“is“clear“to“me“that“doing“a“go•Go“d‘t‘jobŽ¡‘O3Ù(or–UUevš¸ãen“a“fairly“go•Go“d–UUjob)“abGout“prett˜yprin˜ting“is“not“a“simple“task."ŽŸ†C‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[64Ž‘ ]ަ‘63×Y‘ÿ*ªes,›this–ïßis“true.‘AdIn“terms“of“Pretzel,˜\doing“a“go•Go“d–ïßjob“abGout“prett•¸ãyprin“ting"‘ïßisŽ¡‘63×writing–Ùya“go•Go“d›Ùyprett•¸ãyprin“ting˜grammar.‘þ4F‘ÿ*ªor˜simple˜languages˜y“ou˜migh“t˜spGend˜aŽ¡‘63×daš¸ãy–Inor“t˜w˜o“preparing“a“go•Go“d–Ingrammar,‘KÏbut“for“more“complex“languages“(and“moreŽ¡‘63×complex–ˆÎwishes“to“the“loGok“of“the“output)“yš¸ãou“migh˜t“spGend“w˜eeks“and“still“not“bGeŽ¡‘63×happ¸ãy‘ÿ*ª.ŽŽŽŒ‹ì" ½\È ýN£8‘'¿¬Ã2.3.‘ÇWRITING–UUPRETTYPRINTING“GRAMMARS‘vó²17ŽŽ ˜G þc㎠ÿ~œrŸŸæd‘FôÎnul‘‚ØlŽŽ’ª¹²empt¸ãy‘UUcommandŽŽŽŽ¤ ‘FôÎindentŽŽ’ª¹²inden¸ãts–UUthe“next“line“a“little“moreŽŽŽŽ¡‘FôÎoutdentŽŽ’ª¹²tak•¸ães›UUbac“k˜the˜last˜inden“tation˜(de-inden“t)ŽŽŽŽ¡‘FôÎfor–ÿ}'c“eŽŽ’ª¹²forces–UUa“line“breakŽŽŽŽ¡‘FôÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽŽ’ª¹²denotes–UUa“pGossible“space“for“a“line“breakŽŽŽŽ¡‘FôÎopt‘ª¨µnŽ‘\*º²,‘UUµn–Ǹ2“f²0µ;–ª¨:“:“:Ž‘ÿ÷;‘ª¨²9¸gŽ’ª¹²denotes–‹an“optional“line“break“with“the“con-Ž¡’ª¹tinš¸ãuation–{line“inden˜ted“a“litte“with“respGect“toŽ¡’ª¹the–¯.normal“starting“pGosition.‘SThis“line“breakŽ¡’ª¹will–UUscore“a“pGenalt¸ãy“of“10µn².ŽŽŽŽŸ0‘FôÎb‘ÿ}'ackupŽŽ’ª¹²denotes–UUa“small“bac¸ãkspaceŽŽŽŽ¡‘FôÎbig‘‰ffŽ‘®for–ÿ}'c“eŽŽ’ª¹²forces–žLa“line“break“and“inserts“a“little“extraŽ¡’ª¹spaceŽŽŽŽŸ‘FôÎno‘‰ffŽ‘®indentŽŽ’ª¹²causes–UUthe“curren¸ãt“line“to“bGe“output“ ushleftŽŽŽŽ¡‘FôÎc–ÿ}'anc“elŽŽ’ª¹²obliterates–Uan¸ãy“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘8[²,‘TûÎoptŽ‘Ó.²,‘TûÎfor–ÿ}'c“eŽ‘$üÕ²orŽ¡’ª¹Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ’ÓÙì²command–ÛPthat“immediatly“precedesŽ¡’ª¹or–çfolloš¸ãws“it“and“also“cancels“an˜y“Îb‘ÿ}'ackupŽ‘# ²com-Ž¡’ª¹mand–UUthat“follo¸ãws“it.ŽŽŽŽŽŽŽŸqÇ‘v£Figure–UU2.1:‘qÇList“of“format“command“primitiv¸ãesŽŽŽŸ¼™‘'¿¬Í2.3.1Ž‘Pÿ¬Mo`difying–€an“existing“grammarŽ©uT‘'¿¬²If–ã_yš¸ãou're“luc˜ky‘ÿ*ª,‘ásomeb•Go“dy–ã_else“had“done“the“w˜ork“already“for“y˜ou.‘äIn“suc˜h“cases,ޤ ‘'¿¬simply–Äêgrab“a“copš¸ãy“of“the“t˜w˜o“Pretzel“input“ les,‘ Îrun“Èpretzel-it“²and“o “y˜ouŽ¡‘'¿¬go.‘NThe–„×Pretzel“homepage“[14Ž‘ ]“should“bšGe“a“go˜o˜d“starting“p˜oin¸ãt“for“the“quest“for“aŽ¡‘'¿¬prett•¸ãyprin“ting–UUgrammar“for“y¸ãour“language.Ž¡‘6¿¬But–what“if“this“grammar“doGesn't“suit“yš¸ãour“preferences?‘UßWhat“if“it“prett˜yprin˜tsŽ¡‘'¿¬ugly–~ÜcoGde?‘î[W‘ÿ*ªell,‘‰=then“yš¸ãou“ha˜v˜e“to“plunge“in˜to“the“ les“and“moGdify“them.‘î[MakingŽ¡‘'¿¬small–2ècš¸ãhanges“that“will“w˜ork“is“quite“easy–ÿ*ª.‘fMF“or–2èexample,‘9Êif“y˜ou“only“dislik˜e“the“w˜a˜yŽ¡‘'¿¬certain–>àsymš¸ãbGols“come“out“of“the“prett˜yprin˜ter,‘C]loGok“in“the“formatted“tok˜en“ le“andŽ¡‘'¿¬try–Í’to“ gure“out,‘ë¡where“yš¸ãou“can“c˜hange“it.‘Ú}Or“if“y˜ou“dislik˜e“forced“line“breaks“atŽ¡‘'¿¬certain–Üplaces,‘ý¬just“go“inš¸ãto“the“grammar“and“remo˜v˜e“the“Îfor–ÿ}'c“eŽ‘ βfrom“the“attributeŽ¡‘'¿¬de nition.Ž¡‘6¿¬If–k”yš¸ãour“wishes“co˜v˜er“more“ma‘Ž8jor“aspGects“of“the“la˜y˜out,‘q$then“y˜ou“should“mak˜e“aŽ¡‘'¿¬copš¸ãy––mof“the“ le“and“rename“it“to“something“that“re ects“the“c˜hange.‘2%Also,‘¼œy˜ou“migh˜tŽ¡‘'¿¬put–¤³a“new“commen¸ãt“at“the“bšGeginning“of“the“ le“that“describ˜es“who“y¸ãou“are“and“whatŽ¡‘'¿¬this–Çénew“grammar“doGes“di erenš¸ãtly“than“the“grammar“y˜ou“started“from.‘ɃNo˜w“y˜ouŽ¡‘'¿¬can–hAstart“to“expšGerimen¸ãt.‘ª‹The“go˜o˜d“thing“ab˜out“this“is“that“yš¸ãou“can“alw˜a˜ys“fallŽ¡‘'¿¬bacš¸ãk–(xto“the“original“cop˜y“and“start“from“there“again.‘bÓIf“y˜ou“get“y˜our“new“grammarŽ¡‘'¿¬w•¸ãorking,‘æ›con“tact–Éthe“Pretzel“home“page“[14Ž‘ ]“so“it“can“bGe“added“to“the“list“of“ lesŽ¡‘'¿¬for–l\certain“languages.‘¶ÝOther“pGeople“can“then“use“yš¸ãour“grammar“and“don't“ha˜v˜e“toŽ¡‘'¿¬go–UUthrough“the“same“w¸ãork“again.Ž¡‘6¿¬F‘ÿ*ªor–#[similar“languages“(likš¸ãe“Ja˜v‘ÿqÇa“and“ÇC²)‘#&y˜ou“could“try“to“tak˜e“a“grammar“forŽ¡‘'¿¬the–[u rst“one“and“try“to“moGdify“it“that“it“ ts“the“second“one.‘„&In“an¸ãy“case,‘\üstudyingŽ¡‘'¿¬existing–UUgrammars“is“alw•¸ãa“ys›UUv“ery˜helpful˜if˜y“ou˜don't˜ha“v“e˜m“uc“h˜expGerience.ŽŸ¸˜‘'¿¬Í2.3.2Ž‘Pÿ¬W‘þàriting–€a“new“Grammar“from“Scratc hަ‘'¿¬²If–çyš¸ãou're“unluc˜ky‘ÿ*ª,‘ý%and“y˜ou“can't“ nd“a“suitable“grammar“then“y˜ou“will“ha˜v˜e“to“startŽ¡‘'¿¬from–­scratcš¸ãh.‘[If“y˜ou're“in“this“situation,‘ there“are“t˜w˜o“pGossible“w˜a˜ys“of“con˜tin˜uing:ŽŸ¼™‘3ø1.ŽŽŽ‘@¿®Most–“æprogramming“languages“are“con¸ãtext“free“and“so“there“should“bGe“a“con-Ž¡‘@¿®text–µfree“grammar“for“yš¸ãour“language“a˜v‘ÿqÇailable“either“in“the“reference“w˜orksŽ¡‘@¿®(i.e.–¸Nthe“b•Go“oks)–¸Nthat“\de ne"“the“language,‘ or“somewhere“in“the“in¸ãternet,ŽŽŽŒ‹ýK ½\È ýN£8‘63ײ18’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜G ý„‘O3Ù²where–$Dthere“could“bGe“compilers“for“yš¸ãour“language“a˜v‘ÿqÇailable“in“the“source,‘.andޤ ‘O3Ùif–}‹so,‘ǘa“con¸ãtext“free“grammar“for“the“parser“of“that“compiler“is“almost“al-Ž¡‘O3Ùw•¸ãa“ys–ܽincluded“there.‘þY‘ÿ*ªou“could“start“with“suc¸ãh“a“grammar“and“simply“addŽ¡‘O3Ùformatting–UUinstructions“to“the“rules“as“y¸ãou“wish.ŽŸM´‘Bl»2.ŽŽŽ‘O3ÙY‘ÿ*ªou–jcould“start“enš¸ãtirely“from“scratc˜h,‘oßloGok“at“the“language“and“start“writingŽ¡‘O3Ùa›„prett•¸ãyprin“ting˜grammar˜that˜w“orks˜with˜the˜coGde˜y“ou˜are˜w“orking˜on.‘X,ThisŽ¡‘O3Ùmighš¸ãt–^™seem“more“w˜ork“than“the“ rst“alternativ˜e,‘òbut“sometimes“is“still“feasible.ŽŸ›h‘E3×T‘ÿ*ªo–jgo“with“the“ rst“alternativ•¸ãe,‘¯Dy“ou–jwill“ha•¸ãv“e–jto“ha•¸ãv“e–ja“full“blo¸ãwn“languageŽ¡‘63×grammar–y*a¸ãv‘ÿqÇailable.‘ÝGBut“these“grammars“(as“for“example“with“ÇC‘y!²or“ÇCŸÿ²++Ž‘Ž<)“tend“toŽ¡‘63×bGe–Iðrather“large“and“ugly‘ÿ*ª,›‡resulting“in“prett•¸ãyprin“ting–Iðgrammars,˜that“are“dicultŽ¡‘63×to–q‡understand“and“dicult“to“moGdify‘ÿ*ª.‘Æ^Ho•¸ãw“ev“er,‘x”a›q‡prett“yprin“ting˜grammar˜doGesn'tŽ¡‘63×ha•¸ãv“e–G;to“bGe“a“full“bloš¸ãwn“language“grammar“after“all.‘mThe“fact“that“suc˜h“a“grammarŽ¡‘63×will–\·solemnly“bšGe“used“to“create“a“\prett•¸ãyprin“ted"–\·translation“of“a“bit“of“source“co˜de“itŽ¡‘63×doGesn't–X†necesserily“ha•¸ãv“e–X†to“ha•¸ãv“e›X†an“y˜resem“blence˜to˜a˜language˜grammar.‘ƒIn˜ÇP‘ÿ ascalŽ¡‘63ײfor–)&instance,‘^ÆforŽ‘^²-,‘^ÆwhileŽ‘¸¼²-“and“ÆelseŽ‘nвless“ÆifŽ‘ Þy²-statemen¸ãts“are“normally“formatted“in“aŽ¡‘63×vš¸ãery–Õ¸similar“w˜a˜y;‘Bso“the“grammar“m˜ustn't“distinguish“bGet˜w˜een“the“three“constructs.Ž¡‘63×This–Îresults“in“prett•¸ãyprin“ting–Îgrammars“that“can“bGe“quite“di eren¸ãt“from“the“normalŽ¡‘63×grammars–UUof“the“programming“languages.‘qÇIn“most“cases“they“are“m•¸ãuc“h‘UUsmaller.Ž¡‘E3×Ho•¸ãw“ev“er,‘½ if›¨Ky“ou˜start˜from˜scratc“h˜and˜don't˜w“an“t˜to˜use˜an˜existing˜referenceŽ¡‘63×grammar,‘šryš¸ãou–Œ could“still“consult“it“once“and“again“if“y˜ou“are“stuc˜k“with“y˜our“o˜wnŽ¡‘63×one.‘áÌLikš¸ãe–Ðthe“language“grammar,‘.¬the“prett˜yprin˜ting“grammar“m˜ust“bGe“able“toŽ¡‘63×parse–Œ‡Îevery“²construct“that“will“appGear“in“the“input.‘\But“it's“no“problem“if“theŽ¡‘63×prett•¸ãyprin“ting–lUgrammar“mighš¸ãt“sw˜allo˜w“coGde“that“isn't“syn˜tactically“correct.‘¶ÆW‘ÿ*ªe'reŽ¡‘63×talking›ÔŽPrett•¸ãyprin“ters˜here˜and˜not˜Compilers.‘ïqSections˜2.3.3˜and˜2.3.5˜will˜elab-Ž¡‘63×orate–ïŸmore“on“the“issue“of“\grammar“correctness."‘@¦In“anš¸ãy“case,‘2ha˜ving“a“loGok“atŽ¡‘63×a•¸ãv‘ÿqÇailable›UUprett“yprin“ting˜grammars˜in˜adv‘ÿqÇance˜helps˜a˜lot.ŽŸ±r‘63×Í2.3.3Ž‘_s×Conš text–€F‘þàree“v˜ersus“Con˜text“Sensitiv˜eŽŸuT‘63ײLošGoking–®at“the“history“of“the“prett•¸ãyprin“ting–®metho˜d“that“Pretzel“emploš¸ãys“(see“c˜hap-Ž¡‘63×ter–w¡5),‘£ùwš¸ãe“can“see“that“the“grammars“that“the“ rst“systems“started“with“w˜ere“con˜textŽ¡‘63×sensitivš¸ãe.‘,‘This–èîmeans“that“there“actually“are“ready“to“use“con˜text“sensitiv˜e“pret-Ž¡‘63×t•¸ãyprin“ting–.šgrammars“around“for“manš¸ãy“languages“suc˜h“as“ÇP‘ÿ ascal“²[29Ž‘ ]“and“ÇC²/ÇCŸÿ²++ŽŽ¡‘63×[33Ž‘ ].‘pThere–POis“evš¸ãen“a“system“similar“to“Pretzel“but“with“a“more“complete“approac˜hŽ¡‘63×called–]¯ÇSPIDER‘]­²[49Ž‘ ]“that“amoung“other“things“created“a“prett•¸ãyprin“ter–]¯from“a“con-Ž¡‘63×text–UUsensitivš¸ãe“prett˜yprin˜ting“grammar.Ž¡‘E3×So–4whš¸ãy“doGes“Pretzel“use“con˜text“free“grammars“an˜yw˜a˜y?‘The“answ˜er“to“thisŽ¡‘63×problem–}Álies“in“the“toGols“that“Pretzel“relies“on.‘ë The“prett•¸ãyprin“ters–}Áthat“PretzelŽ¡‘63×generates–â”are“actually“parsers,‘ù‡and“instead“of“writing“a“whole“new“parser“generator,Ž¡‘63×Pretzel–Ù©relies“on“the“wš¸ãell“kno˜wn“ÇUNIX‘ÙŠ²tošGol“Bison,‘òethat“do˜es“just“the“wš¸ãork“w˜e“need.Ž¡‘63×But,–UUin“e ect,“Bison“input“is“con¸ãtext“free!‘qÇHmmm.Ž¡‘E3×No•¸ãw›u­con“text˜free˜grammars˜are˜a˜little˜more˜restrictiv“e˜than˜con“text˜free˜ones,Ž¡‘63×and–1so“it“is“not“pGossible“to“transform“anš¸ãy“con˜text“sensitiv˜e“grammar“of“y˜our“c˜hoiceŽ¡‘63×inš¸ãto–Ca“con˜text“free“one.‘k±This“is“unfortunate,‘Fºbut“this“is“a“fact“w˜e“ha˜v˜e“to“liv˜e“with.Ž¡‘63×My–Äknoš¸ãwledge“of“formal“language“theory“is“not“v˜ery“deep,‘·Hbut“I‘’suspGect“that“parsingŽ¡‘63×with–ãÙconš¸ãtext“sensitiv˜e“grammars“is“not“trivial“and“that“this“is“the“reason“wh˜y“noŽ¡‘63×generators–UUlikš¸ãe“Bison“exist“in“a“con˜text“sensitiv˜e“ a˜v˜our.Ž¡‘E3×So–°0conš¸ãtext“free“is“what“w˜e“ha˜v˜e“to“liv˜e“with.‘:»F‘ÿ*ªrom“studying“existing“prett˜yprin˜t-Ž¡‘63×ing–ÃWsystems“(again“see“cš¸ãhapter“5“for“details)“it“seems“that“con˜text“sensitiv˜e“is“theŽ¡‘63×w•¸ãa“y–mFto“go“in“prett•¸ãyprin“ting,‘sBand–mFthis“seems“bad“for“Pretzel.Ÿü^ÿ±6ŽŽ‘ 6 ²But“Pretzel“is“a“pro-Ž‘63ן¥á‰ff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»I‘ZÈactually–ZëÔis“»a“quite“sevšÃŽere“restriction“and“will“probably“b‘6¿­¸ŽŽŽ‘@¿®ÇC–UU²(b¸ãy“F‘ÿ*ªelix“G‘úÿÿartner)Ž¡‘@¿®Directory:‘qÇÈlanguages/ceeŽ¡‘@¿®²Files:‘qÇÈcee.ft–UU²and“Ècee.fgŽ©R¾‘6¿­¸ŽŽŽ‘@¿®ÇP‘ÿ ascal–UU²(b¸ãy“F‘ÿ*ªelix“G‘úÿÿartner)Ž¡‘@¿®Directory:‘qÇÈlanguages/pascalŽ¡‘@¿®²Files:‘qÇÈpascal.ft–UU²and“Èpascal.fgަ‘6¿­¸ŽŽŽ‘@¿®²Jaš¸ãv‘ÿqÇa–UU(for“Ènoweb“²b˜y“Lee“Witten˜bGerg)Ž¡‘@¿®Directory:‘qÇÈcontrib/leewŽ¡‘@¿®²Files:‘qÇÈjava.ft–UU²and“Èjava.fgަ‘6¿­¸ŽŽŽ‘@¿®²Jaš¸ãv‘ÿqÇa–UU(for“Ènoweb“²b˜y“F‘ÿ*ªelix“G‘úÿÿartner)Ž¡‘@¿®Directory:‘qÇÈcontrib/noweb/java.latexŽ¡‘@¿®²Files:‘qÇÈjavafx.ft–UU²and“Èjavafx.fgŽ¡‘@¿®²Commenš¸ãts:‘تBased–Çon“the“grammar“b˜y“Lee“Witten˜bGerg“with“sligh˜t“c˜hanges,Ž¡‘@¿®but–UUenhanced“to“do“indexing.ަ‘6¿­¸ŽŽŽ‘@¿®²Jaš¸ãv‘ÿqÇa–UU(for“Ènoweb“²b˜y“Holger“Uhr)Ž¡‘@¿®Directory:‘qÇÈcontrib/huhrŽ¡‘@¿®²File:‘qÇÈjavahu.fgŽ¡‘@¿®²Commenš¸ãts:‘ãŽReplaces–8ãÈjava.fg“²from“Lee“Witten˜bGergs“v˜ersion“in“Ècontrib/leew².ŽŸ>‘'¿¬Alw•¸ãa“ys–UUsee“the“ÈREADME“² les“in“the“directories“for“details.ŽŸkô‘'¿¬Í2.3.5Ž‘Pÿ¬Debugging›€Prett• yprin“ting˜GrammarsŽŸ›Ô‘@¿®²\Rather,‘1&it–([the“need“to“tš¸ãypGe“`È@;²'“after“eac˜h“re nemen˜t]“is“caused“b˜y“anŽ¡‘@¿®error–?Wmade“in“con•¸ãv“erting–?WÈWEB›?R²to“ÈCWEB˜²that“wš¸ãas“nev˜er“corrected,‘C½namelyŽ¡‘@¿®a–ÕÊfailure“to“recognise“the“fundamenš¸ãtally“di eren˜t“roles“of“semicolonsŽ¡‘@¿®in–oïÇP›ÿ ascal“²and“ÇC².“In“ÇP˜ascal“²semicolons“separate“statemen¸ãts,‘v–whetherŽ¡‘@¿®simple–ß5(e.g.,›A¬assignmen¸ãts)“or“compGound,˜so“if“anš¸ãy“suc˜h“statemen˜t“isŽ¡‘@¿®follo•¸ãw“ed›ßsequen“tially˜b“y˜another˜one,‘Ša˜semicolon˜is˜required˜after˜theŽ¡‘@¿® rst;‘œthe–/requiremenš¸ãt“still“holds“if“the“ rst“statemen˜t“is“a“re nemen˜t.Ž¡‘@¿®In–ïother“wš¸ãords,‘U}in“P˜ascal“one“has“`re nemen˜t“¸!“²statemen˜t'“alw˜a˜ys,Ž¡‘@¿®without–&haš¸ãving“to“consider“ÈLINE_END²,“and“without“ha˜ving“to“use“`È@;²'ŽŽŽŒ‹# ½\È ýN£8‘63ײ20’ÈrlÃCHAPTER–UU2.‘ªªUSING“PRETZELŽŽ ˜G ý„‘O3Ù²(either–ura“real“semicolon“is“required“after“it,›½yor“nothing“is,˜e.g.,˜whenޤ ‘O3ÙÈELSE–”{²folloš¸ãws).‘1In‘”¬ÇC“²ho˜w˜ev˜er,‘»5no–”¬sym˜bGol“separates“successiv˜e“statemen˜ts,Ž¡‘O3Ùbut–Bhthings“likš¸ãe“assignmen˜ts“are“expressions“rather“that“statemen˜ts,‘F1andŽ¡‘O3Ùthey–{-only“bGecome“statemenš¸ãts“b˜y“incorpGorating“a“follo˜wing“semicolon.Ž¡‘O3ÙSince–âüre nemenš¸ãts“almost“alw˜a˜ys“stand“for“(compGound)“statemen˜ts,‘ùÛtheyŽ¡‘O3Ùshould–H†bGe“givš¸ãen“that“category;‘LËho˜w˜ev˜er“in“(Levy/Kn˜uth)“ÈCWEB‘H‚²they“areŽ¡‘O3Ùgivš¸ãen–É`the“same“category“as“assignmen˜ts,‘&bwhic˜h“is“`expression'.‘ÍçThisŽ¡‘O3Ùforces–U³one“to“write“a“semicolon“after“eacš¸ãh“re nemen˜t,‘UÊev˜en“though“thatŽ¡‘O3Ùreally–ÈbGecomes“a“spurious“emptš¸ãy“statemen˜t;‘!¢if“suc˜h“an“empt˜y“statemen˜tŽ¡‘O3Ùwš¸ãould–ýmess“up“the“real“syn˜tax“(the“compiler“w˜ould“fail)“then“one“has“toŽ¡‘O3Ùwrite–UU`È@;²'“instead."ŽŸ'‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[62Ž‘ ]ŽŸ&O‘63×Almost–zcertainly‘ÿ*ª,‘ÃËthe“ rst“expGeriences“with“yš¸ãour“o˜wn“(or“other's)“prett˜yprin˜tingŽ¡‘63×grammars–8 will“lead“to“situations“where“source“coGde“is“not“prett•¸ãyprin“ted–8 the“w•¸ãa“yŽ¡‘63×y•¸ãou›œ>w“an“ted˜and˜y“ou˜don't˜kno“w˜wh“y‘ÿ*ª.‘FThe˜insigh“t˜that˜follo“ws˜from˜this˜situationŽ¡‘63×is–Tvš¸ãery“frustrating:‘oPnothing“comes“for“free!‘nSearc˜hing“for“bugs“in“prett˜yprin˜tingŽ¡‘63×grammars–UUis“as“necessary“as“in“normal“programs.ŽŸ1‘63ׯThe–ÕTÈerror“ÆT‘ÿ «ok®9enŽŸ‡'‘63ײIf–Ösa“Pretzel“prett•¸ãyprin“ter–Öscan't“handle“a“sequence“of“input“coGde,‘6ºit“will“outputŽ¡‘63×Înothing²,‘š•not–Yˆevš¸ãen“an“error“message.‘~aBut“there“is“still“a“w˜a˜y“to“notice“this“fact.Ž¡‘63×There–ȵis“a“spGecial“Èerror“²tokš¸ãen“that“ma˜y“bGe“used“in“suc˜h“circumstances.‘ËæY‘ÿ*ªou“canŽ¡‘63×place–it“inš¸ãto“y˜our“grammar“at“an˜y“place,‘and“it“will“matc˜h“a“sequence“of“tok˜ens“notŽ¡‘63×co•¸ãv“ered›UUb“y˜the˜other˜rules˜in˜question.ŽŸ ”‘E3×A‘3rhandy–3zplace“to“put“an“Èerror“²tokš¸ãen“is“righ˜t“at“the“bGeginning“of“the“grammar.Ž¡‘63×Saš¸ãy‘ÿ*ª,‘Óa–ì Èfinal“²tok˜en“is“the“tok˜en“that“ev˜erything“reduces“to“in“y˜our“grammar.‘6)T‘ÿ*ªoŽ¡‘63×notice–UUa“parse“error,“y¸ãou“can“for“example“writeŽ©»‘63×Èfinal‘¿÷:‘?ýexpŽ¡‘`3¿|‘?ýstmtŽ¡‘@³Ñ//–?ýcheck“for“parse“errors:Ž¡‘`3¿|–?ýerror‘ ú{“"syntax“error"“}Ž¡‘63×;ަ‘63ײand–Y;so“the“text“\synš¸ãtax“error"“appGears“in“the“output“ev˜erywhere“Pretzel“w˜asn'tŽ¡‘63×able–UUto“parse“the“input.Ž© ”‘E3×Y‘ÿ*ªou–È%maš¸ãy“place“the“Èerror“²tok˜en“in“an˜y“place“y˜ou“lik˜e,‘äbas“long“as“it“is“on“the“righ˜tŽ¡‘63×hand–7‰side“of“the“colon.‘gØUsing“the“Èerror“²tokš¸ãen“in“other“places“than“at“the“end,‘=~y˜ouŽ¡‘63×ma¸ãy–iproGduce“grammars“that“are“more“robust“and“can“handle“unforseen“constructsŽ¡‘63×more‘UU exibly‘ÿ*ª.ŽŸ1‘63ׯW‘ÿ «atcš®9hing–ÕTthe“P˜arseŽŸ‡'‘63ײThe–Èpretzel-it“²program“o ers“a“È-d“²option“that“proGduces“a“prett•¸ãyprin“ter‘whic“hŽ¡‘63×is–|Hin“\debugging“moGde"“bš¸ãy“default.‘æ This“means“that“during“prett˜yprin˜ting,‘ÆtheŽ¡‘63×program–ù:will“output“a“lot“of“debugging“information“to“the“standard“error“streamŽ¡‘63×(usually–Ñthe“screen).‘äñThis“information“displaš¸ãys“what“kind“of“tok˜en“has“bGeen“readŽ¡‘63×from–ù.the“input“(and“hoš¸ãw“it“loGoks)“and“what“rule“of“the“prett˜yprin˜ting“grammar“hasŽ¡‘63×bšGeen–¤÷c¸ãhosen.‘`®Additionally‘ÿ*ª,‘¸àthe“È-d“²option“pro˜duces“a“ le“that“con¸ãtains“an“analysisŽ¡‘63×of–n yš¸ãour“prett˜yprin˜ting“grammar.‘½©If“y˜our“input“name“is,–tósa˜y‘ÿ*ª,“Èfoo²,“then–n this“ le“willŽ¡‘63×bGe–UUcalled“Èfoo.output².ަ‘E3×Here's–8ãan“example“of“the“debugging“output“(tak¸ãen“from“a“run“on“the“Èsmall-example.simpasŽ¡‘63ײexample):ŽŽŽŒ‹0Ç ½\È ýN£8‘'¿¬Ã2.3.‘ÇWRITING–UUPRETTYPRINTING“GRAMMARS‘vó²21ŽŽ ˜G ý„‘'¿¬ÈStarting‘?ýparseޤ ‘'¿¬Entering–?ýstate“0Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“260“(IFif)Ž¡‘'¿¬Shifting–?ýtoken“260“(IF),“Entering“state“1Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“266“(IDa)Ž¡‘'¿¬Shifting–?ýtoken“266“(ID),“Entering“state“4Ž¡‘'¿¬Reducing–?ývia“rule“7“(line“195),“ID‘ ú->“expŽ¡‘'¿¬state–?ýstack“now“0“1Ž¡‘'¿¬Entering–?ýstate“8Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“259“(BINOP=)Ž¡‘'¿¬Shifting–?ýtoken“259“(BINOP),“Entering“state“11Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“265“(NUM1)Ž¡‘'¿¬Shifting–?ýtoken“265“(NUM),“Entering“state“3Ž¡‘'¿¬Reducing–?ývia“rule“8“(line“196),“NUM‘ ú->“expŽ¡‘'¿¬state–?ýstack“now“0“1“8“11Ž¡‘'¿¬Entering–?ýstate“15Ž¡‘'¿¬Reading–?ýa“token:“Next“token“is“261“(THENthen)Ž¡‘'¿¬Reducing–?ývia“rule“9“(line“197),“exp“BINOP“exp‘ ú->“expŽ¡‘'¿¬[...]Ž¡‘'¿¬Entering–?ýstate“14Ž¡‘'¿¬Reducing–?ývia“rule“2“(line“102),“stmt_list“SEMI“stmt‘ ú->“stmt_listŽ¡‘'¿¬state–?ýstack“now“0Ž¡‘'¿¬Entering–?ýstate“5Ž¡‘'¿¬Now–?ýat“end“of“input.Ž¡‘'¿¬Shifting–?ýtoken“0“($),“Entering“state“19Ž¡‘'¿¬Now–?ýat“end“of“input.Ž© ‘'¿¬²Evš¸ãery–fÅtime,‘–|the“scanner“reads“a“tok˜en,‘–|the“tok˜en“coGde“(lik˜e“ÈIF›f‰²or“ÈID²)˜is“prinš¸ãted“whic˜hŽ¡‘'¿¬is›é…follo•¸ãw“ed˜b“y˜the˜actual˜con“ten“ts˜of˜the˜tok“en˜(lik“e˜\Èa²"˜in˜case˜of˜the˜iden“ti er).Ž¡‘'¿¬Evš¸ãery–tçtime“the“parser“reduces“a“tok˜en,‘|Ëit“prin˜ts“the“rule“that“it“uses.‘Ð|The“n˜um˜bGerŽ¡‘'¿¬of–—€the“rules“and“also“the“state“information“will“bšGecome“clear“if“y¸ãou“lo˜ok“at“theŽ¡‘'¿¬Èsimpas.output–² le“and“learn“abGout“the“inš¸ãternals“of“the“Pretzel“parsing“mec˜hanismŽ¡‘'¿¬(bš¸ãy–UUloGoking“at“the“man˜ual“page“Èbison(1)²).ŽŸ6Ï‘'¿¬ÆCon®9text–ÕTF‘ÿ «ree“againŽŸ‰/‘'¿¬²As–ÛÒdescribšGed“ab˜o•¸ãv“e,‘ýqcon“text–ÛÒfree“grammars“are“prettš¸ãy“restrictiv˜e,‘ýqsometimes“ev˜enŽ¡‘'¿¬more–UUrestrictivš¸ãe“than“w˜e“lik˜e.‘qÇNote“that“rules“lik˜eަ‘'¿¬Èdecl_head–?ýid“:‘¿÷int_like“idŽ¡‘'¿¬;ަ‘'¿¬²to–bsturn“an“Èint‘¡E‰ff&fŽ‘Ç«like“²tokš¸ãen“in˜to“the“head“of“a“declaration“if“it“is“follo˜w˜ed“b˜y“anŽ¡‘'¿¬idenš¸ãti er–UUare“con˜text“senstiv˜e“and“therefore“forbidden.ŽŸ «‘6¿¬See–3Ÿalso“the“next“cš¸ãhapter,‘:]espGecially“section“3.1.4“for“a“few“more“tips“and“tric˜ksŽ¡‘'¿¬for–UUwriting“and“debugging“prett•¸ãyprin“ting‘UUgrammars.ŽŸ6Ï‘'¿¬Í2.3.6Ž‘Pÿ¬Exp`eriencesŽŸ‰/‘@¿®²\With–fÈCWEB²,“there'll“alw•¸ãa“ys–fbGe“something“someone“w•¸ãan“ts–fand“can't“ha•¸ãv“e,Ž¡‘@¿®bšGecause–Åit“tries“to“do“to˜o“m•¸ãuc“h–Åin“its“kš¸ãernel.‘ÀÔWitness“the“recen˜t“com-Ž¡‘@¿®plainš¸ãt–6in“this“newsgroup“from“someone“trying“to“put“mak˜e les“in“theŽ¡‘@¿®ÈCWEB–g³²sources.‘¨îÈCWEAVE“²tries–g·to“bšGe“the“p˜erfect“ÇC‘g³²programming“to˜ol“righ¸ãtŽ¡‘@¿®out–À:of“the“bGoš¸ãx,‘Þ and“so“comes“up“completely“unable“to“handle“mak˜e les."ŽŸV‘@¿®Barry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŽŽŒ‹?ø ½\È ýN£8‘63ײ22’ÇUúÃCHAPTER–UU2.‘ÇUSING“PRETZELŽŽ ˜G ý„‘63ײRemem¸ãb•Ger,‘ï”writing›лgo“o“d˜prett•¸ãyprin“ting˜grammars˜is˜dicult.‘ãùSo˜don't˜o“v“erdo˜it.ޤ ‘63×It's–×Iprett¸ãy“dicult“(if“not“impGossible)“to“come“out“with“a“\complete"“grammar“thatŽ¡‘63×will–Ñ—handle“all“cases“brillianš¸ãtly‘ÿ*ª.‘æŒSo“if“y˜ou're“happ˜y“with“the“w˜a˜y“y˜our“cošGde“lo˜oks,Ž¡‘63×that's– ne.‘«If“something“turns“out“wrongly‘ÿ*ª,›Bask“y¸ãourself,˜what“actually“Îis“²wrongŽ¡‘63×here?ŽŽŽŒ‹Kµ ½\È ýN£8 ˜G ýÏ‘'¿¬ÊChapter‘Ç 3ŽŸ2‘'¿¬ÅPretzel‘ T{Hac‘ÿ8õkingŽŸ4‘'¿¬²In–ÆÃthis“cš¸ãhapter“w˜e'll“ha˜v˜e“a“loGok“in˜to“the“guts“of“Pretzel.‘BAW‘ÿ*ªe'll“see“ho˜w“the“in˜ternalsޤ ‘'¿¬of–b Èpretzel-it“²wš¸ãork“and“what“other“nice“things“y˜ou“can“do“with“the“system.‘—èThisŽ¡‘'¿¬cš¸ãhapter–ÿis“aimed“at“programmers“who“w˜an˜t“to“proGduce“simple,‘«ecien˜t“and“elegan˜tŽ¡‘'¿¬prett•¸ãyprin“ters–for“their“language.‘HÝHo•¸ãw“ev“er,‘®óI‘œõrecommend–reading“at“least“the“ rstŽ¡‘'¿¬subsection–UUabšGout“adding“ÇC“²co˜de“to“the“rules,“evš¸ãen“when“y˜ou“dislik˜e“hac˜king.ŽŸ ø½‘'¿¬Ì3.1Ž‘L¦Adding–ffó*Œ-øff cmcsc10ÕC“ÌCos3de“to“the“RulesŽŸç‘'¿¬²Y‘ÿ*ªes,‘›éyš¸ãou–mŽcann“add“y˜our“o˜wn“ÇC‘mS²coGde“to“the“attribute“de nition“parts“of“the“formattedŽ¡‘'¿¬grammar–õ%and“formatted“tokš¸ãen“ les.‘ Q8A‘ôºt˜ypical“application“of“this“feature“is“toŽ¡‘'¿¬dynamically–"…tš¸ãypGeset“constructed“t˜ypGe“names“(as“Æt®9ypQÇedefŽ‘(‚y²s“in“ÇC‘"x²or“ÆclassŽ‘L²es“in“Ja˜v‘ÿqÇa)Ž¡‘'¿¬correctly‘ÿ*ª.Ž¡‘6¿¬The–hÓproblem“with“Pretzel“is,‘­³that“wš¸ãe“w˜ould“lik˜e“to“pGerform“di eren˜t“actionsŽ¡‘'¿¬depGending–Üon“the“conš¸ãtext“of“the“tok˜en“that“the“prett˜yprin˜ter“ nds.‘UôF‘ÿ*ªor“example,‘ŽinŽ¡‘'¿¬ÇC‘Oвnormal–O‹idenš¸ãti ers“should“bGe“t˜ypGeset“in“italics,‘P´but“iden˜ti ers“that“are“the“namesŽ¡‘'¿¬of‘cÆt®9ypQÇedefŽ‘(à ²s–cshould“bšGe“t¸ãyp˜eset“in“b˜old.‘› Pretzel“can't“handle“this“situation“withoutŽ¡‘'¿¬tricš¸ãky–þËmanipulations“of“the“attribute“de nitions,‘bGecause“the“t˜ypGe“of“grammar“thatŽ¡‘'¿¬Pretzel–§(uses“is“essenš¸ãtially“con˜text“free“(see“section“2.3.3“for“a“discussion“of“relatedŽ¡‘'¿¬problems).ŽŸå/‘'¿¬Í3.1.1Ž‘Pÿ¬Example–€for“T‘þàok ensŽŸuT‘'¿¬²Hoš¸ãw–rŒhandle“this“situation?‘ÉkPretzel“allo˜ws“y˜ou“to“add“ÇC‘rB²coGde“to“y˜our“attributeŽ¡‘'¿¬de nitions.‘tHere–89is“a“small“example,‘pòhoš¸ãw“this“could“bGe“used“in“formatted“tok˜enŽ¡‘'¿¬ les:ޤn®‘'¿¬È[a-zA-Z][a-zA-Z0-9_]*‘ÿôID› ú{–?ý"{\\it“"˜[escaped_underlines(yytext)]“"}"“}Ž¡‘6¿¬²The–±purpGose“of“this“line“is“to“scan“tokš¸ãens“that“are“iden˜ti er“names“and“returnޤ ‘'¿¬\ÈID²"‘Ô®t•¸ãypGe›ÔÏtok“ens˜to˜the˜prett“yprin“ting˜parser,‘ô­but˜also˜to˜mo•Gdify˜the˜app“earanceŽ¡‘'¿¬of–üEthe“matc¸ãhed“text“bšGefore“returning.‘f–In“this“example“there“is“ÇC‘ü²co˜de“inside“theŽ¡‘'¿¬attribute–›7de nition.‘CmThis“coGde“is“encircled“in“angled“brac•¸ãk“ets–›7\È[²"“and“\È]²"“andŽ¡‘'¿¬can–jybGe“anš¸ãy“sequence“of“ÇC‘j2²statemen˜ts“with“one“cen˜tral“propGert˜y:‘œThe“coGde“partŽ¡‘'¿¬mš¸ãust–X†reduce“to“the“ÆA®9ttributeŽ‘3̸“²class,‘YRi.e.“the“return“t˜ypGe“m˜ust“me“a“pGoin˜ter“to“anŽ¡‘'¿¬ÆA®9ttributeŽ‘ZŠÅ²ob‘Ž8ject.‘WGThe‘ÓÆA®9ttributeŽ‘5Ðì²class–Óis“a“spšGecial“ÇCŸÿ²++Ž‘”class“that“b˜elongs“to“theŽ¡‘'¿¬Pretzel–UUsystem“and“is“conš¸ãtained“in“the“run˜time“library‘ÿ*ª.Ÿü^ÿ±1ŽŽŽ¡‘6¿¬²T‘ÿ*ªo–8ãthis“e ect,‘qÇthe“Îesc–ÿ}'ap“e“d‘‰ffŽ‘®underlines–8ã²function“called“abGo•¸ãv“e›8ãm“ust˜ha“v“e˜the˜sy“onpsis:Ž‘'¿¬Ÿ ‰ff‰¬Ÿ J=‘ "5Ÿý-:¼1ŽŽŽ‘LÜ»A‘€|description–€¨of“hoÃŽw“to“use“obxäjects“of“this“class“and“related“functions“can“b6²);ŽŸ$‘63×The–İmatc¸ãhed“text“is“accessible“via“a“string“(i.e.“a“Æc®9harŽ‘Fo¸“²v‘ÿqÇariable)“called“ÎyytextŽ‘O¨².‘ATheޤ ‘63×delimiters–»øof“cošGde“are“angled“brac•¸ãk“ets–»øas“explained“ab˜o•¸ãv“e.‘>¨If–»øangled“brac•¸ãk“ets‘»øapp˜earŽ¡‘63×in–Ó„the“ÇC‘Óc²coGde“itself,‘óanš¸ãy“closing“brac˜k˜et“m˜ust“bšGe“escap˜ed“bš¸ãy“a“bac˜kslash“in“orderŽ¡‘63×for–UUPretzel“to“recognize“it“correctly‘ÿ*ª.Ž© ‘E3×T‘ÿ*ªo–?ôhelp“simplify“the“synopsis“of“the“Îesc–ÿ}'ap“e“d‘‰ffŽ‘®underlinesŽ‘Y‰í²function,‘z›wš¸ãe“ma˜y“useŽ¡‘63×spšGecial–Lrfunctions“in“the“run¸ãtime“library“that“b˜elong“to“the“ÆA®9ttributeŽ‘6^*²class.‘nÑTheseŽ¡‘63×are–r,the“t•¸ãw“o–r,functions“Îcr–ÿ}'e“ateŽ›#&²and“ÎjoinŽ‘g².‘ÈKThe“Îcr–ÿ}'e“ateŽ˜²function“tak¸ães“a“string“(i.e“aŽ¡‘63ׯc®9harŽ‘Kµ–¸²)–ÓÀand“turns“it“inš¸ãto“an“attribute.‘í So,‘3[if“y˜ou“ha˜v˜e“written“a“function,‘3[sa˜yŽ¡‘63×Îesc‘‰ffŽ‘®ulŽ‘P u²,›Aéthat–™turns“a“string“in¸ãto“the“same“string“with“escapGed“underlines,˜then“anŽ¡‘63×implemenš¸ãtation–UUof“the“function“abGo˜v˜e“could“loGok“lik˜e“this:ŽŸ$0‘@3ØÆA®9ttributeŽ‘où¸‘UUÎesc–ÿ}'ap“e“d‘‰ffŽ‘®underlinesŽ‘T_Z²(Æc®9harŽ‘¿¸‘UUÎsŽ‘>6²)ަ‘@3ظfަ‘J3ÙÆreturnŽ‘m‡^Îcr–ÿ}'e“ateŽ’‡µ,²(Îesc‘‰ffŽ‘®ulŽ‘ìž²(ÎsŽ‘èá²));ަ‘@3ظgަŸ$‘63ײThe‘agÎjoinŽ‘e ²function–agsimply“joins“t•¸ãw“o–agor“more“(up“to“ten)“attributes“together“in¸ãto“anŽ¡‘63×new‘UUone.ŽŸ.6‘63×Í3.1.2Ž‘_s×Example–€for“GrammarsŽŸ†*‘63ײBut–Ýyš¸ãou“can“do“more“with“this“feature.‘$`Here's“an“example“coGde“fragmen˜t“thatŽ¡‘63×handles–@the“\correct"“formatting“of“Æt®9ypQÇedefŽ‘)b4²s“in“ÇC².“In“ÇC‘²yš¸ãou“can“construct“y˜ourŽ¡‘63×oš¸ãwn–¨Óshorthands“for“t˜ypGes“b˜y“using“the“Æt®9ypQÇedefŽ‘.±š²construct,‘ý²th˜us“making“normalŽ¡‘63×iden•¸ãti ers›óµlik“e˜ÎL‘ÿ}'engthŽ‘%°²to˜t“ypGe˜names.‘LèHere's˜an˜example,‘Mif˜y“ou're˜not˜aquain“tedŽ¡‘63×with‘UUÇC²:ŽŸ$0‘@3ØÆt®9ypQÇedefŽ‘hé!in®9tŽ‘yúãÎL‘ÿ}'engthŽ’—Ã{²;ަ‘@3ØÎL‘ÿ}'engthŽ‘aQÅlŽ‘d膲;ŽŸŸ$‘63×The–Mìidenš¸ãti er“ÎL‘ÿ}'engthŽ‘$dp²has“the“status“of“a“t˜ypšGe“name“and“this“should“b˜e“re ected“inŽ¡‘63×the–UUtš¸ãypGesetting“st˜yle.‘qÇSo“the“w˜a˜y“w˜e“w˜an˜t“it“w˜ould“bGe“lik˜e“this:ŽŸ$0‘@3ØÆt®9ypQÇedefŽ‘hé!in®9tŽ‘yúãLengthŽ’*ײ;ަ‘@3ØÆLengthŽ‘f¹!ÎlŽ‘jOâ²;ŽŸŸ$‘E3×The–jsidea“bšGehind“a“simple“solution“to“this“problem“is“to“use“a“simple“lo˜okupŽ¡‘63×table–‡to“kš¸ãeep“trac˜k“of“all“iden˜ti ers“that“ha˜v˜e“bGeen“Æt®9ypQÇedefŽ‘(}{²ed.‘_-Then,‘(°if“w˜e“ha˜v˜e“toŽ¡‘63×prett•¸ãyprin“t–ó5an“iden•¸ãti er,‘Õw“e–ó5simply“loGok“inš¸ãto“the“table“and“from“the“result“w˜e“kno˜wŽ¡‘63×whether–UUw¸ãe“can“use“bGoldface“or“italics.ަ‘E3×A‘ƒ$prett•¸ãyprin“ter–ƒYfor“ÇCŸü^ÿ±2ŽŽ‘ÿ—²mighš¸ãt“ha˜v˜e“rules“lik˜e“these“to“handle“Æt®9ypQÇedefŽ‘*f¦²statemen˜ts:Ž©$‘63×Ètypedef–?ý:“TYPEDEF_LIKE“INT_LIKE“ID‘î[“install($3);“]Ž¡’3_{–?ý$1“"\\“"“$2“"\\“{\\bf“"“$3“"}"“}Ž¡‘63×;ަ‘63ײ(W‘ÿ*ªe–\£assume“that“Îinstal‘‚ØlŽ‘"—²is“a“function“that“installs“an“iden¸ãti er“in“the“loGokup“tableŽ¡‘63×and–UUthat“Îlo‘ÿ}'okupŽ‘"¤d²is“a“function“that“tells“us“if“an“iden¸ãti er“is“in“the“table.)ŽŸ ‘E3×What–œ§w¸ãe“see“here“is“called“Îstarting‘êc–ÿ}'o“de².‘48Starting–œ§cošGde“is“co˜de“in“angled“brac•¸ãk“etsŽ¡‘63×that–Úsis“placed“bGefore“the“attribute“de nition.‘HÑIt“can“conš¸ãtain“an˜y“sequence“of“ÇC‘ÚT²coGdeŽ‘63ן|]‰ff‰¬Ÿ J=‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»LikÃŽe–ÕXthe“one“in“the“Ïlanguages/cee“»subÿÜ{“[lookup($1)“?“create("{\\bf“")“:Ž¡’¿ÿUcreate("{\\it–?ý")]“$1“"}"“}Ž¡‘'¿¬;ަ‘'¿¬²Note– ¶that“wš¸ãe“are“making“use“of“the“conditional“expression“of“ÇC².“Remem˜bGer“thatŽ¡‘'¿¬the–ÎcošGde“within“the“attribute“de nition“has“to“turn“out“as“t¸ãyp˜e“ÆA®9ttributeŽ‘2Þ¸“²and“soŽ¡‘'¿¬wš¸ãe–´Ãuse“the“Îcr–ÿ}'e“ateŽ‘!—T²function“again“to“turn“a“string“in˜to“an“attribute.‘So“here“againŽ¡‘'¿¬wš¸ãe–¥Ðuse“coGde“Îwithin“²attribute“de nitions“and“all“in“all,‘¹ïw˜e“can“use“iden˜ti ers“as“ÈidŽ¡‘'¿¬²tokš¸ãens–UUin“the“grammar“and“kno˜w“that“they“are“t˜ypGeset“correctly‘ÿ*ª.Ž¡‘6¿¬Apart–~nfrom“cošGde“b˜efore“the“attribute“de nition“and“co˜de“within“attribute“de -Ž¡‘'¿¬nitions,‘ƒ¿there–zwcan“also“bšGe“co˜de“after“the“attribute“de nition“whic¸ãh“is“called“ÎendingŽ¡‘'¿¬c–ÿ}'o“de².‘ÉÁEnding–r¨cošGde“can“b˜e“anš¸ãy“kind“of“sequence“of“ÇC‘r_²statemen˜ts.‘ÉÁThey“will“bGeŽ¡‘'¿¬executed–Îafter“²the“attribute“de nition“has“bGeen“put“together“and“Îb–ÿ}'efor“e–²the“ nalŽ¡‘'¿¬tok•¸ãen›Ðìiden“ti er˜id˜returned.‘äŒSo˜in˜e ect˜y“ou˜y“ourself˜ma“y˜pla“y˜GoGd˜and˜return˜aŽ¡‘'¿¬tok•¸ãen›/ˆiden“ti er˜y“ourself.‘_The˜follo“wing˜extract˜from˜a˜formatted˜tok“en˜ le˜is˜anŽ¡‘'¿¬example:ަ‘'¿¬È[a-zA-Z][a-zA-Z0-9]*‘îID›ÿô{–?ý**“}˜[“return(ID);“]ަ‘'¿¬²Here,‘the‘í1ÆreturnŽ‘%Ø’²statemenš¸ãt–í1is“executed“just“bGefore“the“prett˜yprin˜ting“scanner“itselfŽ¡‘'¿¬returns–¿the“ÈID‘‹²tokš¸ãen,‘Qso“here“y˜ou“could“lea˜v˜e“the“ending“coGde“a˜w˜a˜y“and“nothingŽ¡‘'¿¬wš¸ãould–¡ƒbGe“c˜hanged.‘VPBut“of“course,‘´Žy˜ou“could“put“an“ÆifŽ‘ øY²statemen˜t“there“and“returnŽ¡‘'¿¬something–@Oelse“as“yš¸ãou“wish.‘jÅThe“sym˜bGolic“names“of“all“the“tok˜ens“ma˜y“bGe“accessedŽ¡‘'¿¬with–UUthe“coGde“parts“simply“bš¸ãy“their“names“y˜ou“ga˜v˜e“them.Ž¡‘6¿¬No•¸ãw›UUy“ou˜migh“t˜w“onder,˜what˜the˜sequenceަ‘'¿¬È[a-zA-Z][a-zA-Z0-9]*–îID“[–?ýreturn(ID);“]ަ‘'¿¬²w•¸ãould›0'mean.‘Ž¡‘'¿¬#include"attr.h"Ž¡¡‘'¿¬class–?ýPscan“{Ž¡‘'¿¬public:Ž¡‘2?¦Pscan(istream*)‘?ý{};Ž¡‘2?¦~Pscan()‘?ý{};Ž¡‘2?¦virtual–?ýint“scan(Attribute**)“=“0;Ž¡‘'¿¬};ަ‘'¿¬²A‘NOPretzel–Nscanner“m¸ãust“bšGe“asso˜ciated“with“an“ÇCŸÿ²++Ž‘ÜËinput“stream“ob‘Ž8ject“that“isŽ¡‘'¿¬passed–»‰to“the“constructor“of“the“class.‘¤bThe“scanner“will“read“c¸ãharacters“from“thisŽ¡‘'¿¬input–stream“when“scanning.‘IThe“actual“scanning“if“pGerformed“inside“the“Îsc‘ÿ}'anŽŽ¡‘'¿¬²mem¸ãbšGer–£Ôfunction.‘]DIt's“return“co˜des“are“inš¸ãtegers“and“iden˜tify“the“tok˜en“that“it“hasŽ¡‘'¿¬just–UUscanned.‘qÇIf“the“input“is“empt¸ãy‘ÿ*ª,“it“returns“0.Ž¡‘6¿¬The–*psubšGclass“that“Pretzel“pro˜duces“will“alw•¸ãa“ys–*pb˜e“a“sub˜class“of“the“ab˜o•¸ãv“e‘*pclass.Ž¡‘'¿¬It's–UUin¸ãterface“is“similar:ަ‘'¿¬Èclass–?ýPSCAN_NAME“:“public“Pscan“{Ž¡‘'¿¬public:Ž¡‘2?¦PSCAN_NAME(istream*);Ž¡‘2?¦~PSCAN_NAME();Ž¡‘2?¦int‘?ýscan(Attribute**);Ž¡‘'¿¬};ަ‘'¿¬²The–y©name“of“the“generated“class“is“ÈPSCAN‘¡E‰ff&fŽ‘Ç«NAME‘y ²b¸ãy“default“and“has“to“bGe“rede nedŽ¡‘'¿¬using–UUpreproGcessor“macros,“suc¸ãh“as“for“exampleަ‘'¿¬È#define–?ýPSCAN_NAME“Pscan_for_pascalަ‘'¿¬²By––1default“the“name“of“the“deriv¸ãed“subšGclass“will“b˜e“ÈPpscan².‘2A‘–header“ le“con¸ãtainingŽ¡‘'¿¬the–#Wderivš¸ãed“scanner“class“could“loGok“lik˜e“this“(b˜y“default“the“header“ le“is“calledŽ¡‘'¿¬ÈPpscan.h²).‘qÇNote–UUthat“there“is“no“precaution“against“double“inclusion.ަ‘'¿¬È/*–?ýheader“file“for“a“prettyprinting“scanner“*/Ž¡¡‘'¿¬/*–?ýNB:“This“file“is“NOT“protected“against“double“inclusion!“*/Ž¡¡‘'¿¬#include–?ý"Pscan.h"“//“include“abstract“base“classŽŽŽŒ‹‰+ ½\È ýN£8‘63ײ28’¶«NÃCHAPTER–UU3.‘ÇPRETZEL“HA¸ãCKINGŽŽ ˜G ý„¤ ‘63×È#ifndef‘?ýPSCAN_NAMEŽ¡‘63×#define–?ýPSCAN_NAME“PpscanŽ¡‘63×#endifŽ¡¡‘63×class–?ýPSCAN_NAME“:“public“Pscan“{Ž¡‘63×public:Ž¡‘@³ÑPSCAN_NAME(istream*);Ž¡‘@³Ñ~PSCAN_NAME();Ž¡‘@³Ñint‘?ýscan(Attribute**);Ž¡‘63×};Ž©V‘63ײThis–â×is“exactly“the“default“header“ le“that“y¸ãou“can“ nd“in“the“Èinclude“²directoryŽ¡‘63×of–½the“Pretzel“distribution.‘©$If“Pretzel“is“installed“on“yš¸ãour“system,‘×y˜ou“should“ ndŽ¡‘63×this–Ðd le“(and“the“header“ le“for“the“abstract“base“class)“in“the“global“Pretzel“includeŽ¡‘63×directory‘UUtoGo.Ÿü^ÿ±3ŽŽŽŸ‘‘63×Í3.2.2Ž‘_s×The›€Prett• yprin“ting˜P“arserŽŸ~8‘63ײThe–Kinš¸ãterface“to“the“prett˜yprin˜ting“parser“is“similar“in“structure“to“the“prett˜yprin˜tingŽ¡‘63×scanner.‘qÇW‘ÿ*ªe›UUha•¸ãv“e˜an˜abstract˜base˜class˜called˜ÈPparse˜²that˜has˜this˜in“terface:ަ‘63×È#includeŽ¡‘63×#include"attr.h"Ž¡‘63×#include"output.h"Ž¡¡‘63×class–?ýPparse“{Ž¡‘63×public:Ž¡‘@³ÑPparse()‘?ý{};Ž¡‘@³Ñ~Pparse()‘?ý{};Ž¡‘@³Ñvirtual–?ýint“prettyprint(istream*,“ostream*)“=“0;Ž¡‘@³Ñvirtual–?ýint“prettyprint(istream*,“Output*)“=“0;Ž¡‘63×};ަ‘63ײThere–T}are“the“usual“functions“to“create“and“destroš¸ãy“a“prett˜yprin˜ting“parser“plusŽ¡‘63×an›’èo•¸ãv“erloaded˜virtual˜mem“bGer˜function˜Îpr‘ÿ}'ettyprintŽ‘2Dz.‘*The˜normal˜use˜of˜Îpr‘ÿ}'ettyprintŽŽ¡‘63ײuses–,ÇCŸÿ²++Ž‘hinput“and“output“streams.‘xKIt“reads“from“an“input“streams“and“writesŽ¡‘63×prett•¸ãyprin“ted–UUcoGde“to“the“output“stream.Ž© Ç‘E3×The–>Ñsecond“vš¸ãersion“of“this“mem˜bšGer“has“an“ÎOutputŽ‘%˜@²class“p˜oin¸ãter“as“second“argu-Ž¡‘63×menš¸ãt.‘šÙThis–¸[is“a“v˜ersion“for“expGerts.‘šÙSee“section“3.6“for“an“example“ho˜w“to“utilizeŽ¡‘63×this.ަ‘E3×The›Å­prett•¸ãyprin“ting˜parser˜class˜whic“h˜is˜actually˜generated˜is˜again˜a˜subGclass˜ofŽ¡‘63×this–*jabstract“base“class.‘cyIt's“name“ma¸ãy“bšGe“rede ned“using“ÇC‘*_²prepro˜cessor“macros.ŽŸV‘63×Èclass–?ýPPARSE_NAME“:“public“Pparse“{Ž¡‘63×public:Ž¡‘@³ÑPPARSE_NAME();Ž¡‘@³Ñ~PPARSE_NAME();Ž¡‘@³Ñint–?ýprettyprint(istream*,“ostream*);Ž¡‘@³Ñint–?ýprettyprint(istream*,“Output*);Ž¡¡‘@³Ñvoid‘?ýdebug_on();Ž¡‘@³Ñvoid‘?ýdebug_off();Ž¡‘63×};Ž‘63ן݉ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»This–ÕXdirectory“will“usually“bަ‘'¿¬#include‘?ý"Ppparse.h"ަ¦‘'¿¬int–?ýmain“()“{ަ‘<¿ Ppparse‘?ýprettyprinter;ަ‘<¿ prettyprinter.prettyprint(&cin,&cout);ަ‘<¿ return(0);ަ‘'¿¬}Ž¡‘'¿¬²Firstly‘ÿ*ª,‘öthe–Õßactual“prett•¸ãyprin“ter–Õßclass“is“included.‘óeThen“w¸ãe“declare“a“simple“pret-ަ‘'¿¬t•¸ãyprin“ter–cmand“simply“call“Îpr‘ÿ}'ettyprintŽ‘2—™².‘œHere,‘fóthe“input“and“output“streams“are“con-ަ‘'¿¬nected–ªto“the“standard“input“and“the“standard“output.‘pIf“this“ÎmainŽ‘ Ó²routine“isަ‘'¿¬compiled–°Îand“link¸ãed“with“the“ob‘Ž8jects“proGduced“from“the“output“of“Pretzel,‘¬theަ‘'¿¬prett•¸ãyprin“ter–æwill“wš¸ãork“as“spGeci ed“in“the“t˜w˜o“input“ les.‘L¬The“prett˜yprin˜ting“parserަ‘'¿¬inš¸ãternally–UUcalls“the“prett˜yprin˜ting“scanner“b˜y“its“default“in˜terface.Ž‘'¿¬ŸU8‰ff‰¬Ÿ J=‘ "5Ÿý-:¼4ŽŽŽ‘LÜ»The–¥>information“proÃŽvided“using“the“Ï-d“»option“of“Ïpretzel-it“»program“comes“from“using“theseŽŸ €functions–ÕX(see“section“2.3.5).ŽŽŽŒ‹’ ½\È ýN£8‘63ײ30’¶«NÃCHAPTER–UU3.‘ÇPRETZEL“HA¸ãCKINGŽŽ ˜G ý„‘63×Ì3.3Ž‘[:Building–ffa“Pretzel“prett•ŒÌyprin“ter›ffb“y˜HandŽŸ÷=‘63ײIf–¡yš¸ãou“need“to“proGduce“a“prett˜yprin˜ting“moGdule“b˜y“hand“y˜ou'll“ha˜v˜e“to“directlyޤ ‘63×in•¸ãv“ok“e›”tPretzel,–ä; ex,“Bison˜and˜y•¸ãour˜ÇCŸÿ²++Ž‘"°compiler˜in˜the˜righ“t˜order.‘/#T‘ÿ*ªo˜easeŽ¡‘63×this,‘"çy¸ãou–Æ—can“use“the“ÈMakefile“²in“the“ÇP‘ÿ ascal“²subGdirectory“of“the“distributionŽ¡‘63×(Èlanguages/pascal²).ŽŸ ’9‘E3×T‘ÿ*ªo–r)proGduce“(only)“the“prett•¸ãyprin“ting–r)parser“from“the“ le“Èpascal.fg“²for“example,Ž¡‘63×yš¸ãou–UUcould“t˜ypGe“the“follo˜wing:Ž©¶¬‘;sÔÈ$–?ýpretzel“-g“pascalŽ¡‘63×This–?ýis“pretzel,“version“2.0.Ž¡‘63×Processing–?ýthe“formatted“grammar“file“(pascal.fg“->“pascal.y).Ž¡‘63×No–?ýerrors“found.Ž¡‘;sÔ$–?ýbison“-d“pascal.yŽ¡‘63×pascal.y–?ýcontains“21“shift/reduce“conflicts.Ž¡‘;sÔ$–?ýmv“pascal.tab.h“ptokdefs.hŽ¡‘;sÔ$–?ýg++“-c“-I$PRETZEL_INCLUDE“-g“pascal.lex.cަ‘63ײW‘ÿ*ªe–Ðassume“that“the“ÈPRETZEL‘¡E‰ff&fŽ‘Ç«INCLUDE‘Ïè²en•¸ãvironmen“t–Ðv‘ÿqÇariable“pGoin¸ãts“to“the“PretzelŽ¡‘63×include–Ídirectory‘ÿ*ª.‘ñ/The“È-d“²option“of“Bison“will“proGduce“a“tok¸ãen“header“ le“thatŽ¡‘63×the–ògscanner“expGects“(the“scanner“mš¸ãust“kno˜w,‘¬whic˜h“tok˜ens“the“parser“a˜w˜aits“andŽ¡‘63×whic•¸ãh››«tok“en˜coGdes˜they˜ha“v“e).‘DÈThe˜scanner˜expGects˜these˜de nitions˜under˜theŽ¡‘63×name‘UUÈptokdefs.h².ŽŸ ’9‘E3×The›ÛŠabGo•¸ãv“e˜sequence˜of˜commands˜should˜lea“v“e˜a˜Èpascal.tab.o˜² le˜in˜y“ourŽ¡‘63×directory‘ÿ*ª.‘i„This–§éis“the“ob‘Ž8ject“coGde“of“the“prett•¸ãyprin“ting–§éparser“with“the“defaultŽ¡‘63×in¸ãterface–ʸ(i.e.“the“generated“class'“name“is“ÈPpparse“²and“is“declared“in“the“includeŽ¡‘63× le–tnÈPpparse.h²).‘ÏY‘ÿ*ªou“can“noš¸ãw“use“this“prett˜yprin˜ter“in“y˜our“o˜wn“programs:‘¯ùb˜yŽ¡‘63×including–ithe“header“ le“the“prett•¸ãyprin“ter–iclass“will“bGecome“visible;‘©sb¸ãy“linking“theŽ¡‘63×ob‘Ž8ject–û¸with“yš¸ãour“o˜wn“program“y˜ou'll“get“y˜our“executable.‘Sè(Note“that“y˜ou'll“need“toŽ¡‘63×proš¸ãvide–Ýøa“prett˜yprin˜ting“scanner“y˜ouself“in“this“case“or“simply“proGduce“a“suitableŽ¡‘63×one–UUin“a“similar“w•¸ãa“y–UUusing“Pretzel.)ŽŸ$‘63×Ì3.4Ž‘[:Obtaining–ffa“Pretzel“Prett•ŒÌyprin“ting‘ffMos3duleŽŸ÷=‘63ײIn– nthe“preceding“section“I‘ @ha•¸ãv“e– nexplained“hoš¸ãw“to“proGduce“a“Pretzel“prett˜yprin˜terŽ¡‘63×b•¸ãy›§^hand.‘gâNo“w˜w“e'll˜see˜ho“w˜y“ou˜can˜c“hange˜the˜default˜in“terface˜of˜the˜proGducedŽ¡‘63×prett•¸ãyprin“ting–UUscanner“and“parser.ŽŸ‘63×Í3.4.1Ž‘_s×The›€Prett• yprin“ting˜ScannerŽŸ…v‘63ײSa•¸ãy‘ÿ*ª,‘Öíy“ou–½need“a“prett•¸ãyprin“ting–½scanner“class“called“ÎF‘ÿ;¼o–ÿ}'osc“anŽ‘* y²in“a“header“ le“calledŽ¡‘63×ÈFooscan.h².‘8üAll–ªóyš¸ãou“ha˜v˜e“to“do“is“to“mak˜e“a“cop˜y“of“the“default“header“ le“ÈPpscan.hŽ¡‘63ײ(whic•¸ãh›{Ty“ou˜can˜ nd˜in˜the˜Pretzel˜include˜directory),‘¦îc“hange˜its˜name˜to˜ÈFooscan.h².Ž¡‘63×Then–UUyš¸ãou“ha˜v˜e“to“c˜hange“the“one“single“Æ#de neŽ‘-õH²statemen˜t“therin,“i.e.“instead“ofަ‘63×È#ifndef‘?ýPSCAN_NAMEŽ¡‘63×#define–?ýPSCAN_NAME“PpscanŽ¡‘63×#endifަ‘63ײy•¸ãou'll›UUha“v“e˜to˜writeަ‘63×È#define–?ýPSCAN_NAME“Fooscanަ‘63ײWithin–G3yš¸ãour“formatted“tok˜en“ le,‘Jy˜ou'll“ha˜v˜e“to“tie“in“the“same“de nition“lik˜e“this:ŽŽŽŒ‹¨~ ½\È ýN£8‘'¿¬Ã3.5.‘ÇMUL‘ÿ*ªTIPLE–UUPRETZEL“MODULES“IN“THE“SAME“PR¸ãOGRAM‘)ùu²31ŽŽ ˜G ý„‘'¿¬È%{ޤ ‘'¿¬#define–?ýPSCAN_NAME“FooscanŽ¡‘'¿¬%}Ž©S‘'¿¬²It–¯[is“impšGortan¸ãt“that“this“text“app˜ears“in“the“declarations“section“of“the“formattedŽ¡‘'¿¬scanner–UU le,“i.e.“bšGefore“the“ rst“line“that“con¸ãtains“the“double“p˜ercen¸ãt“sign“`È%%²'.ŽŸ ]Æ‘6¿¬Compiling–/¿and“linking“the“source“proGduced“bš¸ãy“Pretzel“and“ ex“y˜ou'll“get“theŽ¡‘'¿¬ob‘Ž8ject–€ïcoGde“that“conš¸ãtains“the“desired“prett˜yprin˜ting“scanner.‘ô–The“scanner“expGectsŽ¡‘'¿¬to–©æ nd“a“tok¸ãen“header“ le“under“the“default“name“Èptokdefs.h“²with“de nitions“ofŽ¡‘'¿¬the–symš¸ãbGolic“names“and“tok˜en“coGdes“of“the“tok˜ens“it“should“bGe“able“to“scan.‘\`EitherŽ¡‘'¿¬yš¸ãou–NâproGduce“this“ le“b˜y“hand“or“y˜ou“let“Bison“do“the“job“for“y˜ou“(using“the“È-dŽ¡‘'¿¬²option–ç)if“yš¸ãou“ha˜v˜e“a“prett˜yprin˜ting“grammar).‘'CLoGok“in˜to“a“standard“Èptokdefs.hŽ¡‘'¿¬² le–Æ to“see“what“it“should“conš¸ãtain.‘ÃéThe“name“of“the“tok˜en“header“ le“Èptokdefs.hŽ¡‘'¿¬²maš¸ãy–µalso“bGe“c˜hanged.‘ÄçY‘ÿ*ªou“ha˜v˜e“to“de ne“the“ÈPTOKDEFS‘¡E‰ff&fŽ‘Ç«NAME‘‚²macro“within“y˜ourŽ¡‘'¿¬formatted–UUtokš¸ãen“ le“lik˜e“this:ަ‘'¿¬È%{Ž¡‘'¿¬#define–?ýPTOKDEFS_NAME“"fooscantoks.h"Ž¡‘'¿¬%}ަ‘'¿¬²Noš¸ãw–o_the“scanner“will“include“the“ le“Èfooscantoks.h“²and“loGok“for“tok˜en“coGde“de -Ž¡‘'¿¬nitions–#Úin“there.‘aI(Again,‘-Àthis“rede nition“m¸ãust“bGe“in“the“declarations“section“of“theŽ¡‘'¿¬formatted–UUtok¸ãen“ le.)ŽŸ1'¿¬Í3.4.2Ž‘Pÿ¬The›€Prett• yprin“ting˜P“arserŽŸ#Ù‘'¿¬²Changing–³0the“inš¸ãterface“of“the“prett˜yprin˜ting“parser“w˜orks“in“a“similar“w˜a˜y“as“justŽ¡‘'¿¬explained–#Sfor“the“prett•¸ãyprin“ting–#Sscanner.‘ÛÁThe“di erences“lie“in“the“macro“namesŽ¡‘'¿¬that›UUha•¸ãv“e˜to˜bGe˜rede ned.ŽŸ ]Æ‘6¿¬The–}Xname“of“the“derivš¸ãed“prett˜yprin˜ting“parser“class“is“ÈPPARSE‘¡E‰ff&fŽ‘Ç«NAME².“If“y˜ou“sa˜yŽ¡‘'¿¬in–UUthe“de nitions“section“of“the“formatted“grammar“ le“for“exampleަ‘'¿¬È%{Ž¡‘'¿¬#define–?ýPPARSE_NAME“FooppŽ¡‘'¿¬%}ަ‘'¿¬²then–î…yš¸ãour“prett˜yprin˜ter“class“will“bGe“called“ÈFoopp².‘=XIn˜ternally“it“expGects“the“pret-Ž¡‘'¿¬t•¸ãyprin“ting–°Yscanner“with“it's“default“in¸ãterface“(i.e.“under“the“names“ÈPpscan“²for“theŽ¡‘'¿¬class–Øvand“Èptokdefs.h“²for“the“tokš¸ãen“header“ le).‘û*If“y˜ou“rede ne“the“same“macrosŽ¡‘'¿¬as–³in“the“formatted“tokš¸ãen“ le,‘then“y˜ou“rede ne“the“in˜terface“under“whic˜h“the“pret-Ž¡‘'¿¬t•¸ãyprin“ter–v"expGects“the“scanner.‘Ô.So“lines“likš¸ãe“these“in“the“formatted“grammar“w˜ouldŽ¡‘'¿¬urge–UUthe“prett•¸ãyprin“ter–UUto“use“a“ÈFooscan“²class“ob‘Ž8ject“for“scanning:ަ‘'¿¬È%{Ž¡‘'¿¬#define–?ýPPARSE_NAME“FooppŽ¡‘'¿¬#define–?ýPSCAN_NAME“FooscanŽ¡‘'¿¬%}ŽŸ#J‘'¿¬Ì3.5Ž‘L¦Multiple–sPretzel“Mos3dules“in“the“same“Pro-ŽŸ‘L¦gramŽŸ• ‘'¿¬²Using–{m¸ãultiple“Pretzel“mošGdules“within“a“single“program“has“b˜een“greatly“simpli edŽ¡‘'¿¬b•¸ãy›>in“troGducing˜the˜ob‘Ž8ject˜orien“ted˜in“terface˜that˜has˜bGeen˜explained˜in˜section˜3.2.Ž¡‘'¿¬The–Émain“thing“is“to“cš¸ãhange“the“names“of“the“t˜w˜o“scanners/parsers“proGduced“b˜yŽŽŽŒ‹ µ´ ½\È ýN£8‘63ײ32’¶«NÃCHAPTER–UU3.‘ÇPRETZEL“HA¸ãCKINGŽŽ ˜G ý„‘63ײPretzel–Çéto“something“distinct“and“then“to“compile“and“link“then“together.‘ɃThat'sޤ ‘63×the‘UUtheory‘ÿ*ª.Ž¡‘E3×But–“«there's“a“problem“here:‘òthe“scanners“and“parsers“proGduced“b¸ãy“ ex“and“BisonŽ¡‘63×conš¸ãtain–Œa“couple“of“global“v‘ÿqÇariables“whose“names“will“clash“when“y˜ou“try“to“linkŽ¡‘63×them–©Dtogether.‘8mThis“maš¸ãy“bGe“circum˜v˜en˜ted“b˜y“using“spGecial“options“of“ ex“and“BisonŽ¡‘63×to–¼µcš¸ãhange“the“pre x“of“these“globals“when“a“scanner/parser“is“built.‘§çAs“I‘¼šha˜v˜en'tŽ¡‘63×needed–Ä×this“feature“in“the“past“(but“only“tested“it),‘á½I‘IJha•¸ãv“en't–Ä×prepared“an“additionalŽ¡‘63×option–,Ìto“Èpretzel-it“²to“do“this“in“a“nice“and“easy“w•¸ãa“y‘ÿ*ª.‘dDA“t–,Ìthe“momenš¸ãt“y˜ou'll“stillŽ¡‘63×ha•¸ãv“e–rto“consult“the“man¸ãual“pages“Èflex(1)²,‘‰úÈflexdoc(1)“²and“Èbison(1)“²for“details.Ž¡‘63×If–!òthis“is“a“feature“yš¸ãou“need,‘,9tell“me“and“I'll“add“it“to“Èpretzel-it“²(see“also“c˜hapterŽ¡‘63×6,–UU\F›ÿ*ªuture“W˜ork").Ž¡‘E3×Another–pthing“that“sounds“inš¸ãteresting,‘vËbut“that“I‘pha˜v˜e“not“tested“y˜et,‘vËis“to“useŽ¡‘63×sevš¸ãeral–binstances“of“a“single“prett˜yprin˜ter“class“proGduced“b˜y“Pretzel“in“the“sameŽ¡‘63×program.‘÷"If–Éyš¸ãou“ha˜v˜e“ev˜er“tried“it,‘ŒæI'm“v˜ery“in˜terested“in“y˜our“results“(see“c˜hapterŽ¡‘63×6,–UU\F›ÿ*ªuture“W˜ork"“again).ŽŸ í/‘63×Ì3.6Ž‘[:Prett•ŒÌyprin“ting–fffor“non-LŸüû+‘ú+ÆAŽŽn¹ÌT‘ýL¨Ÿ32EŽ‘èdXiansŽŸç‘O3Ù²\Of–À?course“ÈCWEAVE‘À²doGes“visual“formatting,‘Þat“least“for“the“part“that“can-Ž¡‘O3Ùnot–ÞbšGe“left“to“b˜e“visually“formatted“b¸ãy“T‘þU>Ÿ'EŽ‘ãxX:‘KŒit“issues“forced“line“breaks,Ž¡‘O3Ùexplicit–}cš¸ãhanges“of“inden˜tation“lev˜el“etc.‘¯@The“logical“markup“is“reallyŽ¡‘O3Ùconš¸ãtained–ñ#in“the“source“doGcumen˜t,‘and“not“(fully)“in“the“in˜termediateŽ¡‘O3Ù le–¦ÖproGduced“bš¸ãy“ÈCWEAVE².“Ho˜w˜ev˜er“ÈCWEAVE‘¦Á²doGes“not“do“complete“visualŽ¡‘O3Ùformatting:‘®Tfor–óœinstance“manš¸ãy“sym˜bGols“lik˜e“opšGerators“are“pro˜duced“asŽ¡‘O3Ùmacros,‘h½so–1¨that“yš¸ãou“can“easily“c˜hange“their“appGearance“b˜y“o˜v˜erridingŽ¡‘O3Ùthe–üGdefault“de nitions,‘&and“breaking“of“long“lines“is“also“left“to“T‘þU>Ÿ'EŽ‘ãxX'sŽ¡‘O3Ùline–UUbreaking“algorithm."ŽŸÕ„‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[60Ž‘ ]ŽŸ+“‘63×Pretzel–©öwš¸ãas“build“with“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“in“mind,‘¿but“this“doGesn't“necessarily“mean“that“y˜ouŽ¡‘63×are–Mrestricted“to“using“this“as“bacš¸ãk“end“of“y˜our“prett˜yprin˜ter.‘YThrough“the“w˜a˜yŽ¡‘63×that–¡œPretzel“wš¸ãas“designed,‘ô®it“is“quite“easy“to“extend“it“to“w˜ork“with“an˜y“otherŽ¡‘63×markup–Ôformatting“system.‘FßHo•¸ãw“ev“er,‘î[if›Ôy“ou˜are˜opting˜for˜immediate˜screen˜outputŽ¡‘63×or–Athings“likš¸ãe“ÇHTML²,“y˜ou're“not“lost“either.‘]ÀFirst,‘%Ew˜e'll“see“ho˜w“to“handle“the“ rstŽ¡‘63×case,–UUand“then“let's“go“and“loGok“at“things“lik¸ãe“ÇHTML².ŽŸÙ¡‘63×Í3.6.1Ž‘_s×Other–€Markup“F‘þàormattersŽŸuT‘63ײInš¸ãternally‘ÿ*ª,‘«—all–šVpieces“of“coGde“that“handle“the“direct“output“of“c˜haracters“or“formatŽ¡‘63×commands–‹to“the“output“stream“are“encapsulated“in“a“ÇCŸÿ²++Ž‘@class“called“ÆOutputŽ‘(J÷².Ž¡‘63×The–Þinš¸ãterface“and“implemen˜tation“of“this“class“are“describGed“in“the“Ènoweb“²sourceŽ¡‘63× le–ÁÈoutput.nw“²in“the“Èoutput“²subšGdirectory“of“the“Pretzel“distribution.‘@^F‘ÿ*ªrom“lo˜okingŽ¡‘63×at–hBthis“ le,‘¬ýy¸ãou'll“see“that“there“is“an“abstract“base“class“ÆOutputŽ‘-w²and“that“theŽ¡‘63×standard–™Üclass,‘¿[whicš¸ãh“Pretzel“prett˜yprin˜ters“use,‘¿[is“the“ÆLatex‘°¡‰ffs4Ž–#Õcw®9eb‘°¡‰ffs4Ž“outputŽ‘dkC²classŸü^ÿ±5ŽŽ‘|s²,Ž¡‘63×a–’ subšGclass“of“ÆOutputŽ‘(Qý².‘'åIt“is“within“this“sub˜class“that“the“actual“translation“of“theŽ¡‘63×format–âÑcommand“Îfor–ÿ}'c“eŽ‘n²inš¸ãto“the“string“\È\pretzelforce{}²"“tak˜es“place“for“example.Ž¡‘E3×If–Ûyš¸ãou“are“going“for“something“lik˜e“T‘ÿ*ªro ,‘óßy˜ou“can“similarly“deriv˜e“a“new“subGclassŽ¡‘63×of‘XïÆOutputŽ‘+qѲ(for–Xïexample“bš¸ãy“cop˜ying“the“original“class)“and“simply“replace“the“textŽ¡‘63×bits–vÎlikš¸ãe“\È\pretzelindent²"“with“the“strings“appropriate“for“T‘ÿ*ªro .‘'šNo˜w,‘£Oy˜ou“ha˜v˜e“toŽ¡‘63×instruct–Føthe“generated“prett•¸ãyprin“ter–Fønot“to“use“the“default“(ÆLatex‘°¡‰ffs4Ž‘#Õcw®9ebŽ‘97P²-)“output,Ž¡‘63×but–‚"to“use“yš¸ãour“new“one.‘+aF‘ÿ*ªor“this“sak˜e,‘¬`the“second“v˜ersion“of“the“Îpr‘ÿ}'ettyprintŽ‘48p²mem˜bGerŽ¡‘63×function–sÛof“the“generated“prett•¸ãyprin“ter›sÛma“y˜bGe˜used˜(see˜section˜3.2,‘{|\The˜PretzelŽ‘63ן‘n‰ff‰¬Ÿ J=‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»The–ÕXname“of“this“class“results“from“the“goal,“to“givšÃŽe“a“LŸþ¢#‘üð¡¼AŽŽ‘ ï»T‘þ•AŸ¸ãEŽ‘MX“ÏCWEB“»touc˜h“to“the“output“[57Ž‘€].ŽŽŽŒ‹!ÂP ½\È ýN£8‘'¿¬Ã3.6.‘ÇPRETTYPRINTING–UUF¸ãOR“NON-LŸýó4‘üffó/¡8)Ïcmsl8ÚAŽŽx‘ÃT‘þU>Ÿ'EŽ‘ãxXIANS’ùé²33ŽŽ ˜G ý„‘'¿¬Inš¸ãterface").‘ÓOSimply– ‚pass“an“ob‘Ž8ject“of“y˜our“new“output“class“to“the“function“andޤ ‘'¿¬the›°prett•¸ãyprin“ter˜will˜use˜it˜instead.‘‚ By˜deriving˜a˜new˜subGclass,‘ÆÏT‘ÿ*ªro ˜and˜LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxXŽ¡‘'¿¬prett•¸ãyprin“ters›UUma“y˜co•Gexist˜p“eacefully‘ÿ*ª.ŽŸþ6‘'¿¬Í3.6.2Ž‘Pÿ¬Going–€for“ó.Œ-ø cmcsc10ÙHTMLŽŸuT‘'¿¬²What–«iif“yš¸ãou“don't“ha˜v˜e“a“real“markup“formatting“system“at“hand“and“w˜an˜t“to“goŽ¡‘'¿¬for–UUsomething“in“the“range“of“a“vt100“terminal,“line“prin¸ãter“or“ÇHTML“²page?Ž¡‘6¿¬Bad–¢:news“is“that“yš¸ãou'll“ha˜v˜e“to“do“without“the“full“blo˜wn“format“commandŽ¡‘'¿¬set.‘žºPropGer–dQin¸ãterpretation“of“the“line“breaking“commands“Îbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘7Ï$²and“ÎoptŽ‘Ⅎ,‘htheŽ¡‘'¿¬commands‘$Îb‘ÿ}'ackupŽ‘%Ê\²and‘$Îno‘‰ffŽ‘®indentŽ‘2üá²cannot–$bGe“guaranš¸ãteed“in“these“cases.‘ÝóHo˜w˜ev˜er,Ž¡‘'¿¬go•Go“d–¥®news“is“that“the“Pretzel“distribution“conš¸ãtains“a“deriv˜ed“ÆOutputŽ‘, O²class“calledŽ¡‘'¿¬ÆAscii‘°¡‰ffs4Ž‘#ÕoutputŽ‘j ‘²that–®maš¸ãy“bGe“used“to“output“prett˜yprin˜ted“coGde“with“this“restrictedŽ¡‘'¿¬command–›set“to“the“screen“(or“to“anš¸ãy“device“suitable“for“ÇASCIJ«I‘›²c˜haracters).‘BþTheŽ¡‘'¿¬format–2§commands“that“cannot“bšGe“executed“prop˜erly“are“still“v‘ÿqÇalid,‘9–but“result“in“noŽ¡‘'¿¬actions–ÅBwhen“outputting“cošGde.‘ÁSee“the“ le“Èasciioutput.nw“²in“the“Èoutput“²sub˜di-Ž¡‘'¿¬rectory–UUof“the“Pretzel“distribution“for“details.Ÿü^ÿ±6ŽŽŽ‘'¿¬ ªÂ9‰ff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»An–õ†example“Ïnoweb“»prett•ÃŽyprin“ter–õ†that“emits“ÐHTML‘ô5»coš5[11Ž‘ ]“proš¸ãvide“go•Go“d–>5and“readable“in˜trošGductions“to“the“ eld,‘vwhile“the“pap˜er“b¸ãyŽ¡‘'¿¬Cordes–"Æand“Broš¸ãwn“[9Ž‘]“discusses“the“paradigm“and“the“b•Go“ok–"Æb˜y“Kn˜uth“[32Ž‘ ]“pro˜videsŽ¡‘'¿¬a–*collection“of“related“articles.‘0Concerning“Ènoweb²,‘·šthere“is“a“lot“of“go•Go“d‘*in¸ãtro“ductoryŽ¡‘'¿¬material–›Laš¸ãv‘ÿqÇailable“online“(see“for“example“the“Ènoweb“²home“page“[48Ž‘ ]).‘C­As“y˜ou“willŽ¡‘'¿¬need–N¹Ènoweb“²an•¸ãyw“a“y–N¹to“install“and“run“Pretzel,‘ƒ?it“is“a“go•Go“d–N¹idea“to“try“a“small“exampleŽ¡‘'¿¬noš¸ãw–…_if“y˜ou“are“unaquain˜ted“with“it.‘æLate“sections“will“need“detailed“kno˜wledgeŽ¡‘'¿¬abšGout–еthe“concepts“of“no•¸ãw“eb–еas“explained“in“the“original“pap˜er“b¸ãy“Ramsey“[50Ž‘ ]Ž¡‘'¿¬or–Þ&the“ultimate“reference“to“Ènoweb²'s“inš¸ãterior“b˜y“the“same“author“[47Ž‘ ].‘ ;The“ÈnowebŽ¡‘'¿¬²extensions–Ž‘of“Pretzel“are“still“vš¸ãery“m˜uc˜h“expGeriman˜tal“and“far“from“making“ÈnowebŽ¡‘'¿¬²as›UUpGo•¸ãw“erfull˜as˜language˜depGenden“t˜literate˜programming˜toGols.ŽŸ ²Ê‘'¿¬Ì4.1Ž‘L¦Prett•ŒÌyprin“ting–ffin“ó-߆µTff cmtt12Ønoweb“Ì{“HošŒÌw“it“w˜orksŽŸç‘@¿®²\They–cH[the“prett•¸ãyprin“ting–cH lters]“can“pšGerform“either“or“b˜oth“of“t•¸ãw“o‘cHtasks:ޤ#f‘L¿­¸ŽŽŽ‘V¿®²c•¸ãhoGose›UUfon“ts˜and˜glyphs˜to˜represen“t˜eac“h˜source˜tok“enŽŸ#f‘L¿­¸ŽŽŽ‘V¿®²c•¸ãhoGose›UUinden“tation˜and˜line˜breaks˜of˜y“our˜coGdeŽ¡‘@¿®I‘[î nd–\2these“features“of“more“cost“than“bšGene t“(except“p˜ossibly“whenޤ ‘@¿®preparing–UUfor“b•Go“ok–UUpublication),“but“lots“of“pGeople“lik¸ãe“them.ަ‘@¿®No•¸ãw“eb›³tak“es˜the˜reasonable˜p•Gosition˜that˜the˜programmer˜is˜the˜b“estŽ¡‘@¿®judge–^gof“where“to“put“the“line“breaks“and“hoš¸ãw“m˜uc˜h“to“inden˜t“coGde.Ž¡‘@¿®In–w*some“languages“(Miranda,–¿ŸHaskš¸ãell,“a˜wk,“Icon),“line–w*breaks“and/orŽ¡‘@¿®indenš¸ãtation–Ñcarry“meaning,‘$and“to“c˜hange“them“w˜ould“bGe“to“c˜hange“theŽ¡‘@¿®meaning–UUof“the“user's“program."ŽŽŸK’×lx35ŽŽŒ‹$ÝV ½\È ýN£8‘63ײ36’§RzÃCHAPTER–UU4.‘ªªPRETZEL“MEETS“ÈNOWEBŽŽ ˜G ý„‘O3Ù²Norman–UURamsey“[52Ž‘ ]ŽŸP¬‘63×A‘…þprimary–†Ldesign“goal“in“devš¸ãeloping“Ènoweb“²w˜as“to“ha˜v˜e“a“literate“programmingޤ ‘63×tošGol–LÃthat“w¸ãas“simple“enough“to“learn“easily‘ÿ*ª,‘Nzand“also“suitable“for“easy“mo˜di cationŽ¡‘63×and–t~extensions.‘ÏAThis“second“goal“wš¸ãas“ac˜hiev˜ed“b˜y“it's“\pipGelined“arc˜hitec˜h˜ture"Ž¡‘63×[47Ž‘ ].‘;Inš¸ãternally–‹ÑÈnoweb“²con˜v˜erts“the“input“ les“in˜to“a“stream“of“items“whic˜h“|“lik˜eŽ¡‘63×in–Еa“pipšGeline“|“are“squeezed“through“sp˜ecial“programs“called“Î lters“²that“p˜erformŽ¡‘63×simple–å@transformations“on“these“data“items.‘!ˆThe“format“of“the“data“items“in“theŽ¡‘63×pipšGeline–g†is“called“the“\no•¸ãw“eb–g†pip˜eline“represenš¸ãtation"“whic˜h“in˜terested“readers“canŽ¡‘63×study–9win“detail“elsewhere“[47Ž‘ ].‘h}Devising“a“prett•¸ãyprin“ter–9wfor“Ènoweb“²means“building“aŽ¡‘63×prettš¸ãyprining–UU lter“for“it.‘qÇSuc˜h“a“ lter“can“then“bGe“inserted“in˜to“the“pipGeline.Ž©S‘63×Í4.1.1Ž‘_s×A–€ó1߆µT cmtt12Ünoweb“ÍPrett• yprin“ter–€for“ÙCŽŸ‰‘63ײIn–|†the“Ècontrib/noweb/cee.latex“²y¸ãou“can“ nd“the“de nitions“of“a“simple“pret-Ž¡‘63×t•¸ãyprin“ter–Ë{for“ÇC².“Change“in¸ãto“this“directory“and“loGok“at“the“ les“Ècee.ft“²and“Ècee.fg².Ž¡‘63×They–Ÿ~are“normal“Pretzel“input“ les“that“ha•¸ãv“e–Ÿ~bšGeen“mo˜di ed“slighš¸ãtly“to“w˜ork“withŽ¡‘63×Ènoweb².‘C˜Before–ÊÈw¸ãe“lošGok“at“these“mo˜di cations,‘æ~let's“try“to“build“a“Ènoweb“²prett•¸ãyprin“t-Ž¡‘63×ing–êz lter“ rst.‘N)T‘ÿ*ªo“do“this,‘ÿÙyš¸ãou“can“use“the“È-n“²option“of“Èpretzel-it“²in“the“follo˜wingŽ¡‘63×w•¸ãa“y:ޤ¼‘63×Èpretzel-it–?ý-n“cee“prettyceeŽ¡‘63ײThis–îwill“proGduce“a“Ènoweb“²prett•¸ãyprin“ter–îcalled“Èprettycee“²in“the“curren¸ãt“directory‘ÿ*ª.Ÿü^ÿ±1ŽŽŽ¤ ‘63ײThis–—Ó lter“can“then“bGe“senš¸ãt“in˜to“action“using“the“È-filter“²option“of“Ènoweave².‘9@F‘ÿ*ªorŽ¡‘63×an–UUexample,“t¸ãypGe:ޤ¼‘63×Ènoweave–?ý-delay“-filter“prettycee“ceetest.nw“>“ceetest.texŽ¡‘63ײThis–ëwill“mangle“the“Ènoweb“²input“ le“Èceetest.nw“²and“output“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“source“toޤ ‘63×Èceetest.tex².‘·óNoš¸ãw–l¹run“it“through“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“and“ha˜v˜e“a“loGok“at“the“result.Ÿü^ÿ±2ŽŽ‘ 4f²What“doŽ¡‘63×y¸ãou‘UUthink?ަ‘63×Í4.1.2Ž‘_s×A–€Ünoweb“ÍPrett• yprin“ter–€for“Ja v‘ÿ@aŽŸ‰‘63ײA‘{prett¸ãy›{:go•Go“d˜Pretzel˜prett•¸ãyprin“ter˜that˜w“orks˜with˜Ja“v‘ÿqÇa˜and˜no“w“eb˜can˜bGe˜found˜inŽ¡‘63×the–jfÈcontrib/noweb/java.latex/“²directory“of“the“Pretzel“distribution.‘°ûIt“featuresŽ¡‘63×a–s ne“tuned“prett•¸ãyprin“ting–sgrammar“that“is“quite“robust“(conš¸ãtributed“in“core“b˜yŽ¡‘63×Lee–ZçWittenš¸ãbGerg),‘\Lcorrect“t˜ypšGesetting“of“class“names“(in“b˜old,‘\Las“go˜d“men¸ãt“them“toŽ¡‘63×bGe)–UUand“rudimen¸ãtary“automatic“indexing“facilities.ŽŸ ”+‘E3×After–8ãinstalling“Pretzel“and“making“the“ le“Èprettyjava“²(bš¸ãy“simply“t˜yping“`Èmake²'),Ž¡‘63×try–UUthe“ lter“on“Jaš¸ãv‘ÿqÇa“ les“of“y˜our“o˜wn.‘qÇThe“command“to“use“then“is:ޤ¼‘63×Ènoweave–?ý-delay“-filter“prettyjava“-index“file.nw“>“file.texŽ¡‘63ײNote–œBthat“the“È-filter“²switcš¸ãh“comes“bGefore“È-index².‘FT‘ÿ*ªo“get“this“stu “t˜ypGeset“cor-ޤ ‘63×rectly‘ÿ*ª,‘>yš¸ãour–î¸ le“needs“to“access“the“Èpretzel-noweb.sty“²LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“st˜yle“ le“(whic˜h“getsŽ¡‘63×installed–þwhen“Pretzel“gets“installed).‘_UF‘ÿ*ªor“this“reason,‘)y¸ãou“need“to“input“it“withingŽ¡‘63×y•¸ãour›UUdoGcumen“t.‘qÇThe˜frames˜of˜m“y˜Ènoweb˜² les˜alw“a“ys˜loGok˜lik“e˜this:Ž‘63ן ¨Ù‰ff‰¬Ÿ J=‘ "5Ÿý-:¼1ŽŽŽ‘LÜ»The–î,Ïnoweb“»extensions“of“Pretzel“mšÃŽust“ha˜v˜e“b‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»PšÃŽeople–êðwho“are“in˜terested“in“the“in˜ternals“of“this“opŸ'EŽ‘ãxX“stš¸ãyle“ le“as“w˜ell“asŽ¡‘63×the–+ le“Èpretzel-noweb.sty².‘c°It“is“impGortanš¸ãt“that“the“Ènoweb“²st˜yle“comes“bGefore“theŽ¡‘63×Èpretzel-noweb–^d²st¸ãyle,‘`¨bGecause“the“latter“rede nes“a“macro“from“the“prior“(see“alsoŽ¡‘63×section‘UU4.2).Ž©óÅ‘63×Í4.1.4Ž‘_s×DebuggingŽŸuT‘63ײY‘ÿ*ªou–vmaš¸ãy“debug“the“prett˜yprin˜ting“ lter“b˜y“setting“an“en˜vironmen˜t“v‘ÿqÇariable“calledŽ¡‘63×ÈPRETZEL‘¡E‰ff&fŽ–Ç«NOWEB‘¡E‰ff&fŽ“DEBUG‘c1²to–cnthe“v‘ÿqÇalue“\Èon²".‘!%Debug“information“will“bGe“turned“o “againŽ¡‘63×when–Œßyš¸ãou“Èunset“²the“v‘ÿqÇariable.‘.öThis“is“a“simple,‘´÷but“easy“to“use“methoGd“of“con˜trollingŽ¡‘63×debug–‘%output.‘%6The“output“is“m•¸ãuc“h›‘%lik“e˜the˜one˜explained˜in˜section˜2.3.5˜on˜pageŽ¡‘63×19,‘Ö1and–¼lthe“tips“and“tric¸ãks“from“section“3.1.4“come“in“handy“toGo.‘§ Suggestions“forŽ¡‘63×impro•¸ãv“emen“ts–UUare“w¸ãelcome.Ž¡‘E3×I‘SÃregularly–SÄrun“the“parsing“within“Emacs“(using“the“shell“command“pGossibilit¸ãy)Ž¡‘63×ans–v"then“can“easily“searcš¸ãh“the“debug“output“and“follo˜w“ho˜w“the“tok˜ens“are“putŽ¡‘63×together.ަ‘63×Í4.1.5Ž‘_s×Making–€the“Best“Use“of“ItŽŸuT‘O3Ù²\The–š@one“area“where“language“depšGenden¸ãt“LP‘što˜ols“are“ahead“is“iden¸ãti erŽ¡‘O3Ùindexing,›<but–5ÐI‘5ÈsuspGect“that“for“ÇCŸÿ²++Ž‘Ž<,˜this“is“an“almost“impGossible“taskŽ¡‘O3Ùan•¸ãyw“a“y‘ÿ*ª."ŽŸóà‘O3ÙMatthias–UUNeerac¸ãher“[42Ž‘ ]ŽŸÃ^‘63×Ha¸ãving›këundersto•Go“d˜ho•¸ãw˜Ènoweb˜²prett“yprin“ters˜di er˜from˜normal˜Pretzel˜prett“yprin“t-Ž¡‘63×ers,›]?it–(wis“easy“to“con•¸ãv“ert–(w les“in“either“direction.‘ë,But“no•¸ãw,˜w“e–(walso“get“languageŽ¡‘63×depGendenš¸ãt–ÀWinformation“within“the“prett˜yprin˜ter“nearly“for“free“and“w˜e“can“for“ex-Ž¡‘63×ample–UUstart“to“build“an“index“of“iden¸ãti er“de nitions“and“uses.Ž¡‘E3×F‘ÿ*ªor–UUexample,“in“the“formatted“tokš¸ãen“ le,“y˜ou“could“write:Ž©Ï~‘63×È[a-zA-Z][a-zA-Z0-9_]*‘ÿôIDŽ¡’¹sŒ{"%\n@index–?ýuse“"“+“**“+“"\n"Ž¡’¾³‰"{\\it–?ý"‘ ú[escaped_underlines(yytext)]“"}"“}ަ‘63ײHere,‘‹àev•¸ãery›€øiden“ti er˜will˜ nally˜bGe˜preceded˜b“y˜a˜line˜that˜will˜tell˜the˜indexer˜ofŽ¡‘63×Ènoweb–´Ð²abšGout“the“app˜earance“of“the“idenš¸ãti er“in“this“c˜h˜unk.‘ãÈcee.ft“²or“Èjava.fg²).˜The“prett•¸ãyprin“ting–ï lter“forޤ ‘'¿¬Ènoweb–x³²that“is“prošGduced“should“b˜e“called“Èpretty...‘Ûâ²with“the“dots“replaced“b¸ãy“theŽ¡‘'¿¬programming–UUlanguage“name“(e.g.“Èprettycee“²or“Èprettyjava²).Ž¡‘6¿¬In–¼3the“dev•¸ãelopmen“t–¼3directories“yš¸ãou'll“ nd“spGecial“Ènoweb“² les“mean˜t“to“test“theŽ¡‘'¿¬prett•¸ãyprin“ters,‘žnot–°to“bGe“of“anš¸ãy“programming“use.‘UThey“include“most“of“the“syn˜taxŽ¡‘'¿¬constructs–• of“the“programming“language“in“question.‘1¯These“ les“are“vš¸ãery“instructiv˜eŽ¡‘'¿¬when–Žbuilding“a“new“prett•¸ãyprin“ter–Žfor“no•¸ãw“eb–Žor“testing“one“that“yš¸ãou“ha˜v˜e“c˜hanged.ŽŸ!Ä‘'¿¬Ì4.2Ž‘L¦ProblemsŽŸç‘@¿®²\I‘TÙthink–Uthe“problem“here“is“not“so“m•¸ãuc“h–Uthat“prett•¸ãyprin“ting–Uis“inheren¸ãtlyŽ¡‘@¿®bad–;Ùas“that“manš¸ãy“languages“don't“bGene t“from“it“so“m˜uc˜h.‘iHÇAlgol“²andŽ¡‘@¿®ÇP‘ÿ ascal²,–Ü*I‘ÁbšGeliev¸ãe,“b˜ene t–Á2quite“a“bit“from“appropriate“prett•¸ãyprin“ting.Ž¡‘@¿®These–oèare“languages“where“yš¸ãou“write“out“a“lot“of“whole“w˜ords:‘¦í`bGegin',Ž¡‘@¿®`end',– D`do',“`then'›Ä{.–ªª.“.‘o%Y‘ÿ*ªou˜get˜the˜idea.‘¿8Languages˜lik¸ãe˜ÇC‘IJand˜IconŽ¡‘@¿®depšGend–63a“lot“on“sym¸ãb˜olic“notation.‘bF‘ÿ*ªor“the“large“part,‘nkall“ÈCWEB‘5ù²do˜esŽ¡‘@¿®is–£Hreplace“one“set“of“sym¸ãbšGols“with“another“that“some“p˜eople“happ˜enŽ¡‘@¿®to›MÂprefer.‘[But,–‹Ýstill,“ÈCWEB‘M‚²puts˜reserv•¸ãed˜w“ords˜and˜de ning˜w“ords˜inŽ¡‘@¿®bGoldface–aÊand“iden¸ãti ers“in“italics;‘hwhat“of“that?‘—%In“ÇP‘ÿ ascal²,‘dçdoing“thatŽ¡‘@¿®helps–׎mark“out“the“form“of“a“construct.‘øsIn“ÇC²,“on“the“other“hand,‘øtheŽ¡‘@¿®constructs–à}are“delimited“bš¸ãy“things“lik˜e“paren˜theses“and“braces,‘Gand“soŽ¡‘@¿®putting–Qøthings“in“di erenš¸ãt“t˜ypšGefaces“do˜esn't“help“that“m•¸ãuc“h.‘p¨OK,‘QøÈCWEBŽ¡‘@¿®²inden•¸ãti es,‘ŽÃbut›Py“ou˜don't˜need˜w“ea“v“e˜to˜do˜that;‘ÍsEmacs˜can˜do˜thatŽ¡‘@¿®for–m¥yš¸ãou,‘s¹or“y˜ou“can“do“it“y˜ourself,‘s¹and“the“w˜eb“source“will“bGene t“fromŽ¡‘@¿®it.‘ #The–ßmain“thing“that“I‘Þ¹mighš¸ãt“w˜an˜t“from“Ènoweb“²but“don't“get“isŽ¡‘@¿®tš¸ãypGesetting–-êof“commen˜ts,‘dand“I‘-²can“liv˜e“without“that“bGecause“I‘-²don'tŽ¡‘@¿®need–UUa“great“manš¸ãy“commen˜ts."ŽŸ‘@¿®Barry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŸ‘'¿¬Handling–lúof“commenš¸ãts“in“prett˜yprin˜ting“remains“an“unsolv˜ed“problem“to“date“(seeŽ¡‘'¿¬section–%—5.2.5).‘âŒThis“is“partially“due“to“the“fact“that“that“commen¸ãts“can“crop“upŽ¡‘'¿¬anš¸ãywhere–;¸in“the“coGde“and“that“they“themself“can“again“con˜tain“quoted“coGde.‘i=WithŽ¡‘'¿¬Ènoweb–·ï²this“problem“isn't“so“sevš¸ãere,‘ЕbGecause“c˜h˜unks“mostly“do“not“con˜tain“a“lot“ofŽ¡‘'¿¬commenš¸ãts–Êjas“they“are“mo˜v˜ed“to“the“doGcumen˜tation“parts“of“the“literate“program.Ž¡‘'¿¬But–UUstill“a“nice“w•¸ãa“y–UUof“handling“commen¸ãts“needs“to“bGe“found.Ž¡‘6¿¬Also,‘Öquoted–¶+cošGde“in“do˜cumenš¸ãtation“c˜h˜unks“isn't“prett˜yprin˜ted.‘<¹This“is“partiallyŽ¡‘'¿¬a–ÿJde cit“of“the“prett•¸ãyprin“ter–ÿJAPI‘ÿand“partially“a“structural“problem.‘o¥One“w¸ãouldŽ¡‘'¿¬need›Ót•¸ãw“o˜distinct˜prett“yprin“ters˜to˜handle˜normal˜c“h“unk˜co•Gde˜and˜quoted˜co“deŽ¡‘'¿¬sep•Gerately›¹èb“ecause˜y•¸ãou˜don't˜w“an“t˜to˜ha“v“e˜forced˜line˜breaks˜within˜doGcumen“tation.Ž¡‘6¿¬Another–—‡problem“arises“from“the“Ènoweb.sty“²LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“stš¸ãyle.‘8^The“en˜vironmen˜t“forŽ¡‘'¿¬setting–¹.cošGde“naturally“is“rather“restrictiv¸ãe“and“a“macro“needs“to“b˜e“c¸ãhanged“in“orderŽ¡‘'¿¬to–:½alloš¸ãw“the“Pretzel“macros“to“w˜ork“correctly‘ÿ*ª.Ÿü^ÿ±3ŽŽ‘²All“this“signals,‘sCthat“Pretzel“an“ÈnowebŽ¡‘'¿¬²ha•¸ãv“e–UUnot“bGecome“real“friends“yš¸ãet;“they“still“ha˜v˜e“to“w˜ork“on“their“relationship.Ž‘'¿¬Ÿq¼ä‰ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»I'm–ÕXnot“a“T‘þ•AŸ¸ãEŽ‘MX“freak“after“all.‘Ç Thanks“to“Lee“WittenÃŽbŸ'EŽ‘ãxX,˜and“Standard“ML.“Some“pGeople“ha•¸ãv“eŽ¡‘@¿®made–?ûit“prett•¸ãyprin“t–?ûother“language,‘D@likš¸ãe“Icon“and“Ob‘Ž8ject-Orien˜ted“T‘ÿ*ªur-Ž¡‘@¿®ing.‘+ƒI‘‚Rha•¸ãv“en't–‚‡bGeen“o•¸ãv“erwhelmed›‚‡b“y˜the˜results,‘¬±but˜then˜I'm˜notoriouslyŽ¡‘@¿®dicult–UUto“conš¸ãvince“of“the“v‘ÿqÇalue“of“prett˜yprin˜ting."ŽŸ!+‘@¿®Norman–UURamsey“[51Ž‘ ]ŽŸ¥×‘'¿¬The–LHterm“Îpr‘ÿ}'ettyprinting“²means“the“rearrangemen¸ãt“of“a“program's“source“coGde“toŽ¡‘'¿¬illuminate–¥ƒit's“logical“structure“and“thš¸ãus“enhance“readabilit˜y‘ÿ*ª.‘bPThe“term“goGes“bac˜kŽ¡‘'¿¬to–eHenry“Ledgard“and“his“\Programming“Pro•¸ãv“erbs"›e[35Ž‘ ].‘!¬Prett“yprin“ting˜has˜bGecomeŽ¡‘'¿¬a–ß¿ eld“of“inš¸ãterest“bGecause“man˜y“of“toGda˜ys“pGopular“programming“languages“are“soŽ¡‘'¿¬called––/\free-format"“languages,‘¼jwhere“there“are“basically“no“column-pGosition“or“line-Ž¡‘'¿¬bGoundary–UUrestrictions“on“statemenš¸ãts,“declarations,“or“commen˜ts.Ž¡‘6¿¬As–ð©a“matter“of“fact,‘W}formatting“and“all“other“aspšGects“of“readabilit¸ãy“dep˜endŽ¡‘'¿¬hea¸ãvily– Ðon“pGersonal“taste“and“skill.‘•7This“has“lead“to“a“wide“range“of“suggestionsŽ¡‘'¿¬and–h9standards“concerning“the“formatting“of“programming“languages,‘lòespGecially“forŽ¡‘'¿¬the–q­ÇP‘ÿ ascal“²[23Ž‘ ]“language“[1Ž‘,“2Ž›q®,“3Ž˜,“6Ž˜,“10Ž› q¯,“16Ž˜,“18Ž˜,“20Ž˜,“34Ž˜,“37Ž˜,“45Ž˜,“40Ž˜].‘%åThe“consistency“ofŽ¡‘'¿¬these–äpropGosals“has“also“enabled“construction“of“automatic“formatting“algorithmsŽ¡‘'¿¬and–Œ toGols“that“are“usually“called“Îpr›ÿ}'ettyprinters‘^,²(or“Îindenting‘±Âpr˜o˜gr˜ams‘Ò!²).‘êIn“theŽ¡‘'¿¬literature–:general“examples“of“prett•¸ãyprin“ters›:ha“v“e˜bGeen˜presen“ted˜among˜others˜forŽ¡‘'¿¬the–­blanguages“ÇAlgol“²[39Ž› ,“59Ž‘ ­d],–ÎúPL/I‘­8[8Ž‘],“ÇLisp–­b²[15Ž˜,“19Ž› ­d,“65Ž˜,“66Ž˜],›ÎúAda“[43Ž‘ ],˜and“of“courseŽ¡‘'¿¬for–UUÇP‘ÿ ascal“²[21Ž‘ ,“22Ž› UW,“3Ž‘UV,“67Ž˜,“1Ž‘UV].Ž¡‘6¿¬Ho•¸ãw“ev“er,‘~àtec“hnological–v‘adv‘ÿqÇance“in“the“area“of“automatic“t¸ãypGesetting“has“led“toŽ¡‘'¿¬a–Æset“of“pšGo•¸ãw“erful–Æformatting“to˜ols“called“Îtyp›ÿ}'esetters²,‘ãor“Îtyp˜esetting‘systems²,‘ãof“whic¸ãhŽ¡‘'¿¬T‘þU>Ÿ'EŽ‘ãxX–9ÿ[30Ž‘ ]“is“maš¸ãybGe“the“most“apparen˜t“to“computer“scien˜tists.‘hªThese“toGols“allo˜w“theŽ¡‘'¿¬preparation–of“doGcumenš¸ãts“in“high“qualit˜y“suited“for“publication.‘*WAmong“the“featuresŽ¡‘'¿¬of–>]these“systems“are“automatic“line-“and“page-breaking,‘BõpšGo•¸ãw“erful‘>]macro-pro˜cessingŽ¡‘'¿¬facilities–}Éand“con•¸ãv“enien“t–}Édevices“for“tš¸ãypGesetting“mathematical“form˜ulas.‘ë#Seen“inŽ¡‘'¿¬this–ƒ4ligh¸ãt,‘άautomatic“program“formatting“is“only“a“simple“instance“of“automaticŽ¡‘'¿¬tš¸ãypGesetting–é[55Ž‘ ,‘Np.“652].‘ -So“prett˜yprin˜ting“algorithms“that“rely“on“professionalŽ¡‘'¿¬t¸ãypšGesetters–hcan“b˜e“simpler“and“pro˜duce“b˜etter“results“at“the“same“time,‘—ˆb˜ecause“a“lotŽ¡‘'¿¬of–¥the“formatting“problems“(e.g.“alignmenš¸ãt,–ÈIline-breaking,“t˜ypGesetting‘¥mathematicalŽ¡‘'¿¬formš¸ãulas)–UUcan“bGe“tak˜en“on“b˜y“the“t˜ypGesetter.Ž¡‘6¿¬In–|õthis“cš¸ãhapter“deals“with“the“general“issue“of“prett˜yprin˜ting.‘è¦It“places“a“widerŽ¡‘'¿¬view–UUon“the“ eld“and“tries“to“loGcate“the“Pretzel“system“within“the“latest“researc¸ãh.ŽŸ Qã‘'¿¬Ì5.1Ž‘L¦Prett•ŒÌyprin“ting–ffwith“F‘þ¦format“CommandsŽŸç‘@¿®²\W‘ÿ*ªell,–ÿÖI›êZm¸ãust‘êvconfess,“I˜w•¸ãas›êvv“ery˜close˜to˜thro“wing˜the˜whole˜ÈCWEB‘êZ²a“w“a“yŽŽŸK’×lx41ŽŽŒ‹*(^ ½\È ýN£8‘63ײ42’©ÛÃCHAPTER–UU5.‘ÇON“PRETTYPRINTINGŽŽ ˜G ý„‘O3Ù²and––switcš¸ãhing“to“something“without“an˜y“prett˜yprin˜ting,‘Kælik˜e“Ènuweb“²orޤ ‘O3ÙÈnoweb².‘–ÌI›aginstalled–a¬Ènuweb²,‘¤Ârewrote“the“ÈMatrix2D˜²example“in¸ãto“it,‘¤ÂranŽ¡‘O3Ùit–µïthrough“and“{“returned“bacš¸ãk“to“ÈCWEB².“I‘µÖprobably“got“spGoiled“b˜y“theŽ¡‘O3Ùnice-lošGoking–UUoutput“it“pro˜duces“{“almost“alw•¸ãa“ys."Ž©P2‘O3ÙJan–UUDv¸ãorak“[12Ž‘ ]ŽŸû‘63×The› prett•¸ãyprin“ting˜methoGd˜used˜b“y˜Pretzel˜can˜bGe˜called˜Îpr‘ÿ}'ettyprinting–i.e.“an“inputŽ¡‘63× le–Pzis“prošGcessed“and“translated“in¸ãto“an“output“ le“according“to“sp˜ecial“rules.‘p)Here,Ž¡‘63×the–Šinput“ le“is“the“patc¸ãh“of“source“cošGde“that“shall“b˜e“prett•¸ãyprin“ted–Šand“the“outputŽ¡‘63× le–Hûis“the“text“suited“for“the“tš¸ãypGesetter.‘m©The“translation“rules“represen˜t“the“spGecialŽ¡‘63×w•¸ãa“y–UUin“whic¸ãh“source“cošGde“should“b˜e“formatted.Ž¡‘E3×The––Šmain“assumption“is“that“wš¸ãe“ha˜v˜e“a“text“formatter“that“uses“Îc–ÿ}'ontr“ol‘»jse-Ž¡‘63×quenc‘ÿ}'es‘IJ(or–ò|Îtags‘Ò!²)“inside“the“actual“text“b•Go“dy–ò|for“spGecifying“all“the“di erenš¸ãt“w˜a˜ysŽ¡‘63×of–0œformatting“(sucš¸ãh“as“fon˜ts,–7õinden˜tation,“spacing,“etc.).‘eŠAnother–0œterm“for“this“w˜a˜yŽ¡‘63×of–Hformatting“con¸ãtrol“is“Îin-text›Yæpr–ÿ}'o“c“e“dur“al˜markup‘·à²and–Hsystems“using“this“tec¸ãhniqueŽ¡‘63×are–wÑcommonly“called“Îdo–ÿ}'cument‘³ c“ompilers–wѲ(though“this“mighš¸ãt“only“refer“to“the“w˜a˜yŽ¡‘63×they–^:w¸ãork,‘`snot“to“viewing“text“proGcessing“as“programming).‘ŒvCommon“examples“ofŽ¡‘63×suc•¸ãh›÷t“yp•Gesetting˜systems˜are˜T‘þU>Ÿ'EŽ‘ãxX˜and˜the˜ÇUNIX˜²to“ols˜Nro /T‘ÿ*ªro .‘ÕñDuring˜theŽ¡‘63×prošGcessing–Îof“the“input“the“only“thing“it“do˜es“is“to“enric¸ãh“the“stream“of“incomingŽ¡‘63×information–Dîwith“spGecial“con¸ãtrol“sequences“that“I‘Dêcall“Îformat‘„Ðc‘ÿ}'ommands“²(or“ÎformatŽ¡‘63×c‘ÿ}'ommand‘ªwprimitives²).‘»YThese–mÛcommands“are“tags“that“are“left“for“the“t¸ãypGesetter“toŽ¡‘63×inš¸ãterpret.‘µrThe–Á9set“of“format“commands“used“b˜y“Pretzel“is“basically“the“initial“setŽ¡‘63×used–Ûbš¸ãy“Kn˜uth.‘óT‘ÿ*ªo“understand“this“proGcedure,‘ü|see“c˜hapter“2.‘óThe“original“doGcu-Ž¡‘63×men•¸ãts›cÞb“y˜Kn“uth˜[29Ž‘ ]˜and˜Kn“uth˜and˜Levy˜[33Ž‘ ]˜presen“t˜the˜algorithm˜in˜(in)formalŽ¡‘63×detail.ŽŸ zb‘63×Ì5.2Ž‘[:A–ffShort“History“of“Prett•ŒÌyprin“tingŽŸç‘O3Ù²\Nevš¸ãertheless–ƒ4I‘‚ÿstrongly“disagree“with“pGeople“sa˜ying“that“prett˜y-prin˜tingŽ¡‘O3Ùis– Ánot“wš¸ãorth“the“e ort“for“an˜y˜one“in“general;‘†wthis“depGends“v˜ery“m˜uc˜hŽ¡‘O3Ùon–4‹ones“particular“situation“and“purpGose.‘fÙIn“some“cases“prett•¸ãy-prin“tingŽ¡‘O3Ùma•¸ãy›UUev“en˜bGe˜the˜main˜reason˜to˜opt˜for˜literate˜programming."ަ‘O3ÙMarc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[61Ž‘ ]ŽŸû‘63×In–ßIthis“section“I‘ß+will“givš¸ãe“a“brief“c˜hronological“o˜v˜erview“o˜v˜er“the“area“of“prett˜yprin˜t-Ž¡‘63×ing,–UUtry“to“structure“the“ eld,“and“will“shoš¸ãw,“ho˜w“the“presen˜t“system“ ts“in˜to“it.ŽŸfÔ‘63×Í5.2.1Ž‘_s×Historical‘€NotesŽŸuT‘63ײThe›èÊprett•¸ãyprin“ting˜of˜coGde˜has˜a˜long˜tradition˜that˜not˜only˜originates˜from˜theŽ¡‘63×compulsion–s/to“tš¸ãypGeset“programs“for“publication.‘ËVThe“readabilit˜y“or“ev˜en“the“sheerŽ¡‘63×bGeautš¸ãy–¬of“a“prett˜yprin˜ted“algorithm“ha˜v˜e“also“bGeen“a“k˜ey“motiv‘ÿqÇation“to“this“part“ofŽ¡‘63×computer‘UUscience.Ž¡‘E3×The–1‡ rst“pšGeople“to“call“sp˜ecial“attenš¸ãtion“to“formatting“issues“w˜ere“probably“P˜e-Ž¡‘63×ter–GvNaur,›J‘ "5Ÿý-:¼2ŽŽŽ‘LÜ»This–this“methoGd“to“ÇP‘ÿ ascal².Ÿü^ÿ±3ŽŽ‘–Þ²The“fact“that“rules“for“la•¸ãy“out–O>and“grammar“are“oftenŽ¡‘63×closely–\¼related“[36Ž‘ ]“also“is“a“strong“indication“that“this“methoGd“is“in“fact“adequate.Ž¡‘63×The–‚¶trend“to•¸ãw“ards–‚¶formal“spšGeci cation“in“this“area“has“indeed“b˜een“\v¸ãery“fortunate"Ž¡‘63×[68Ž‘ ]– Žand“has“also“pro•¸ãv“ed– Žto“bGe“useful“in“other“areas,‘+sucš¸ãh“as“syn˜tax-directed“editorsŽ¡‘63×[56Ž‘ ].Ž© E3×T›ÿ*ªo–0tthis“end“Rose“and“W˜elsh“[55Ž‘ ]“ha•¸ãv“e›0tadv“oGcated˜the˜in“tegration˜of˜format˜rulesŽ¡‘63×within–ñMthe“language“synš¸ãtax“on“the“language“design“lev˜el.‘PoThey“state“that“\programŽ¡‘63×format–ú‡decisions“[should“bGe“put]“in“the“domain“of“the“language's“designer,‘#ÓratherŽ¡‘63×than–»1its“sevš¸ãeral“implemen˜tators“or“n˜umerous“users,‘Úwhic˜h“implies“uniformly“format-Ž¡‘63×ted– programs“of“impro•¸ãv“ed› readabilit“y˜and˜therefore˜usabilit“y‘ÿ*ª."‘‘K[55Ž‘ ,‘7Ìp.˜651]˜TheirŽ¡‘63×idea–üôdošGes“Înot“²try“to“imp˜ose“rigid“formatting“rules“on“users“of“existing“or“future“lan-Ž¡‘63×guages.‘¦wInstead–¼:they“propGose“a“metasyn¸ãtax“and“a“set“of“guidelines“that“constrainŽ¡‘63×and–kdirect“the“language“designer“in“the“placing“of“format“commands.‘ZyThese“formatŽ¡‘63×commands–—Ùinclude“commands“for“indenš¸ãtation,‘½¿as“w˜ell“as“for“line“breaks“and“optionalŽ¡‘63×line–Ùbreaks“(so“called“\fold“options").‘4žThe“metasyn¸ãtax“and“the“guidelines“only“e ectŽ¡‘63×rather–»nglobal“issues“of“formatting“but“ensure“consistency“across“language“bGorders.Ž¡‘63×They–F0also“presenš¸ãt“a“folding“algorithm“that“implemen˜ts“the“format“commands“fromŽ¡‘63×their‘UUlist.ަ‘E3×This–Xtlast“approacš¸ãh“b˜y“Rose“and“W‘ÿ*ªelsh“is“curren˜tly“the“`state“of“the“art'“in“pro-Ž¡‘63×gram›•la•¸ãy“out˜issues.‘1W‘ÿ*ªo•Go“dman˜has˜published˜a˜thorough˜discussion˜of˜this˜sc¸ãhemeŽ¡‘63×and–`Ahas“propGosed“re nemenš¸ãts“[68Ž‘ ]“that“ho˜w˜ev˜er“do“not“alter“the“main“pGoin˜ts.‘’ŒIt“isŽ¡‘63×an–AOapproacš¸ãh“that“in“some“w˜a˜y“surpasses“the“area“of“prett˜yprin˜ting“in“that“it“forcesŽ¡‘63×the–NÙformatting“grammar“to“bGe“equal“to“the“language“reference“grammar.‘ožHo•¸ãw“ev“er,Ž¡‘63×Kn•¸ãuth›“usho“ws˜that˜a˜prettprin“ting˜grammar˜can˜bGe˜m“uc“h˜simpler˜than˜a˜full-size˜lan-Ž¡‘63×guage–kÒgrammar,‘qqbGecause“it“is“able“to“treat“semanš¸ãtically“di eren˜t“con˜tructs“equallyŽ¡‘63×as–UUthey“are“formatted“in“the“same“w•¸ãa“y–UU(e.g.“ÆifŽ‘ ¨²,“ÆforŽ‘ª¦²and“ÆwhileŽ‘!L²statemen¸ãts).Ž‘63ן  …‰ff‰¬Ÿ J=‘ "5Ÿý-:¼3ŽŽŽ‘LÜ»It–gis“inšÃŽteresting“that“Mateti's“solution“w˜as“the“result“of“formalization“(due“to“v˜eri cation“needs)ŽŸ €and–ÕXthat“Oppšthe“ÈWEB“²system“shoš¸ãws,‘BºT‘þU>Ÿ'EŽ‘ãxX“has“bGeen“used“as“a“bac˜k“end“for“a“prett˜yprin˜ter,Ž¡‘'¿¬but–Ó2it“has“remained“the“only“one“that“I‘Óam“a•¸ãw“are–Ó2of.‘ë_This“leads“to“the“question,Ž¡‘'¿¬whš¸ãy–ü™so“little“prett˜yprin˜ters“faciliate“t˜ypGesetters“as“bac˜k“ends“for“their“output?‘T3ThisŽ¡‘'¿¬question–é is“vš¸ãery“striking,‘þ³as“t˜ypšGesetters“o er“p˜o•¸ãw“erful–é capabilities,‘þ³and“for“example,Ž¡‘'¿¬T‘þU>Ÿ'EŽ‘ãxX's–è¥line“breaking“algorithm“has“bšGeen“adv¸ão˜cated“to“b˜e“v¸ãery“suitable“for“exactlyŽ¡‘'¿¬this–UUtask“[28Ž‘ ].ŽŸ ´Ò‘6¿¬OppGen–UUgivš¸ães“an“answ˜er“to“this“in“his“papGer:ަ‘@¿®\Ho•¸ãw“ev“er,‘Šit–L·[the“algorithm]“seems“to“strik¸ãe“a“reasonable“balance“bGe-Ž¡‘@¿®t•¸ãw“een–ô„sophistication“and“simplicit¸ãy‘ÿ*ª,‘áand“to“bšGe“appropriate“as“a“sub˜com-Ž¡‘@¿®pGonenš¸ãt–UUof“editors“and“the“lik˜e."‘qÇ[44Ž‘ ,“p.“466]ަ‘'¿¬It– µis“surely“the“question“whether“yš¸ãou“are“prett˜yprin˜ting“on“screen“or“preparing“aŽ¡‘'¿¬publication.‘.¼But–”Qthe“other“part“of“the“answš¸ãer“is“ma˜ybGe“not“so“ob˜vious“and“has“toŽ¡‘'¿¬do–UUwith“the“traditional“fears“in“the“programming“comm•¸ãunit“y‘ÿ*ª.Ž© ´Ò‘6¿¬A‘Q†lot–Q‡of“prett•¸ãyprin“ters›Q‡ha“v“e˜bGeen˜built˜as˜parts˜of˜larger˜programming˜en“viron-Ž¡‘'¿¬menš¸ãts–.and“w˜ere“constituen˜t“parts“of“this“larger“system.‘WeA‘lac˜k“of“moGdularit˜y“in“theŽ¡‘'¿¬design–Vÿ(as“for“example“the“fundamenš¸ãtal“distinction“presen˜ted“in“these“sections“andŽ¡‘'¿¬visialized–V¾in“ gure“5.1)“often“makš¸ães“the“resuing“of“sub•Gcomp“onen˜ts‘V¾imp“ossible.‘vTheŽ¡‘'¿¬prett•¸ãyprin“ters–UUhide“somewhere“in“the“larger“system“and“are“dicult“to“extract.ަ‘6¿¬Another–ÕpGoinš¸ãt“is“that“an“old“habit“of“programmers“is“their“striv˜e“for“indepGen-Ž¡‘'¿¬dence.›¯They–iÂdo“not“w•¸ãan“t–iÂtheir“systems“to“rely“on“other“systems.˜But“this“habit“isŽ¡‘'¿¬hopšGefully–UUgetting“less“frequen¸ãt“to˜da¸ãy‘ÿ*ª.ŽŸ½Ž‘'¿¬Í5.2.4Ž‘Pÿ¬The–€Set“of“F‘þàormat“CommandsŽŸÅÙ‘'¿¬²The–Eáformat“commands“passed“bGet•¸ãw“een–Eáthe“fronš¸ãt“end“and“the“bac˜k“end“of“the“pret-Ž¡‘'¿¬t•¸ãyprin“ter–›ªare“the“only“means“to“con•¸ãv“ey–›ªthe“formatting“pGolicy“to“the“actual“formatterŽ¡‘'¿¬(see–™. gure“5.1“that“visualizes“the“moGdularitš¸ãy“of“a“prett˜yprin˜ter).‘=RThis“means“thatŽ¡‘'¿¬ev•¸ãery›dkt“ypGesetting˜feature˜m“ust˜bGe˜expressible˜in˜them.‘ŸIn˜conjunction˜with˜thisŽ¡‘'¿¬wš¸ãork–O¢it“is“impGortan˜t“to“ask,‘Ž5if“the“command“set“pro˜vided“in“the“curren˜t“PretzelŽ¡‘'¿¬system–Þfis“sucienš¸ãt“to“format“ev˜ery“desired“feature“that“w˜e“can“pGossibly“think“of.Ž¡‘'¿¬The–5answš¸ãer“is“clearly“`No!',‘oas“there“still“are“opGen“prett˜yprin˜ting“problems.‘V¼W‘ÿ*ªe“willŽ¡‘'¿¬ha•¸ãv“e–UUa“loGok“at“them“later.‘qÇBut“just“hoš¸ãw“sucien˜t“is“the“command“set?ަ‘6¿¬First–¸wš¸ãe'll“loGok“at“whether“it“allo˜ws“full“con˜trol“o˜v˜er“line“breaks“and“inden˜tation.Ž¡‘'¿¬A‘ÈPdetailed–Èncomparison“shoš¸ãws“that“the“command“set“used“b˜y“Rose“and“W‘ÿ*ªelsh“is“aŽŽŽŒ‹.nÞ ½\È ýN£8‘63ײ46’©ÛÃCHAPTER–UU5.‘ÇON“PRETTYPRINTINGŽŽ ˜G þ3¬ŸÞ9Ÿ¾ù‘u Îand–“çformat“c‘ÿ}'ommandsŽŽŽŽ’æÐ5ŸˆûÞ„fd#9‘ÜÆížÌÎóäO£ line10¬ŽŽ’é…ÔŸâe]„fd ƒt‘öžÌÎ-ŽŽ‘Yë韼v«„fdÞóŽ‘a©¯Ÿ¼v«„fdÞóŽ‘iguŸ¼v«„fdÞóŽ‘q%;Ÿ¼v«„fdÞóŽ’ÖŽ{Ÿ¼v«„fd¬QŽ’ÝæöŸ¼v«„fd¬QŽ’å?qŸ¼v«„fd¬QŽ’ì—쟼v«„fd¬QŽ’óðgŸ¼v«„fd¬QŽ’ûH⟼v«„fd¬QŽ’¡]Ÿ¼v«„fd¬QŽ’ ùØŸ¼v«„fd¬QŽ’RSŸ¼v«„fd¬QŽ’ªÎŸ¼v«„fd¬QŽ’ IŸ¼v«„fd¬QŽ’'[ÄŸ¼v«„fd¬QŽ’.´?Ÿ¼v«„fd¬QŽ’6 ºŸ¼v«„fd¬QŽ’=e5Ÿ¼v«„fd¬QŽ’D½°Ÿ¼v«„fd¬QŽ’L+Ÿ¼v«„fd¬QŽ’Sn¦Ÿ¼v«„fd¬QŽ’ZÇ!Ÿ¼v«„fd¬QŽ’bœŸ¼v«„fd¬QŽ’ixŸ¼v«„fd¬QŽ’pÐ’Ÿ¼v«„fd¬QŽ’x) Ÿ¼v«„fd¬QŽ’¥–Ÿ®·^„AºfeŽŽ’¥–ŸÔ¦„÷YfeŽ’¥ÉMŸÔ¦?ŽŽ‘gŸŸÔ¦‰fe}o\ŸÍÕ„ÍÕfeŸñŽ‘|¢’„ÍÕfeŽžfe‰fe}o\ŽŽŽŸ¶Ø;’^´Îstr–ÿ}'e“am–“çof“stringsŽŽŽŽ‘gŸ ÿ}ò0‰fe}o\ŸÍÕ„ÍÕfeŸñŽ‘|¢’„ÍÕfeŽžfe‰fe}o\ŽŽŽŸçi‘wÉD²formatting‘UUalgorithmŽŽŽŽžôO‘^b6ó†›Zcmr5°.ŽŽŽžôO‘cÍt.ŽŽŽžôO‘i8².ŽŽŽžôO‘n£ð.ŽŽŽžôO‘t..ŽŽŽžôO‘yzl.ŽŽŽžôO‘~åª.ŽŽŽžôO’„Pè.ŽŽŽžôO’‰¼&.ŽŽŽžôO’'d.ŽŽŽžôO’”’¢.ŽŽŽžôO’™ýà.ŽŽŽžôO’Ÿi.ŽŽŽžôO’¤Ô\.ŽŽŽžôO’ª?š.ŽŽŽžôO’¯ªØ.ŽŽŽžôO’µ.ŽŽŽžôO’ºT.ŽŽŽžôO’¿ì’.ŽŽŽžôO’ÅWÐ.ŽŽŽžôO’ÊÃ.ŽŽŽžôO’Ð.L.ŽŽŽžôO’Õ™Š.ŽŽŽžôO’ÛÈ.ŽŽŽžôO’àp.ŽŽŽžôO’åÛD.ŽŽŽžôO’ëF‚.ŽŽŽ ÿs‘^b6.ŽŽŽ ÿs‘cÍt.ŽŽŽ ÿs‘i8².ŽŽŽ ÿs‘n£ð.ŽŽŽ ÿs‘t..ŽŽŽ ÿs‘yzl.ŽŽŽ ÿs‘~åª.ŽŽŽ ÿs’„Pè.ŽŽŽ ÿs’‰¼&.ŽŽŽ ÿs’'d.ŽŽŽ ÿs’”’¢.ŽŽŽ ÿs’™ýà.ŽŽŽ ÿs’Ÿi.ŽŽŽ ÿs’¤Ô\.ŽŽŽ ÿs’ª?š.ŽŽŽ ÿs’¯ªØ.ŽŽŽ ÿs’µ.ŽŽŽ ÿs’ºT.ŽŽŽ ÿs’¿ì’.ŽŽŽ ÿs’ÅWÐ.ŽŽŽ ÿs’ÊÃ.ŽŽŽ ÿs’Ð.L.ŽŽŽ ÿs’Õ™Š.ŽŽŽ ÿs’ÛÈ.ŽŽŽ ÿs’àp.ŽŽŽ ÿs’åÛD.ŽŽŽ ÿs’ëF‚.ŽŽŽžôO‘^b6.ŽŽŽŸú‰‘^b6.ŽŽŽŸõÓ‘^b6.ŽŽŽŸï²•‘^b6.ŽŽŽŸêGW‘^b6.ŽŽŽŸäÜ‘^b6.ŽŽŽŸßpÛ‘^b6.ŽŽŽŸÚ‘^b6.ŽŽŽŸÔš_‘^b6.ŽŽŽŸÏ/!‘^b6.ŽŽŽŸÉÃã‘^b6.ŽŽŽŸÄX¥‘^b6.ŽŽŽŸ¾íg‘^b6.ŽŽŽŸ¹‚)‘^b6.ŽŽŽŸ´ë‘^b6.ŽŽŽŸ®«­‘^b6.ŽŽŽŸ©@o‘^b6.ŽŽŽŸ£Õ1‘^b6.ŽŽŽŸžió‘^b6.ŽŽŽŸ˜þµ‘^b6.ŽŽŽŸ““w‘^b6.ŽŽŽŸŽ(9‘^b6.ŽŽŽŸˆ¼û‘^b6.ŽŽŽŸƒQ½‘^b6.ŽŽŽ ÿ}æ‘^b6.ŽŽŽ ÿx{A‘^b6.ŽŽŽ ÿs‘^b6.ŽŽŽžôO’ëF‚.ŽŽŽŸú‰’ëF‚.ŽŽŽŸõÓ’ëF‚.ŽŽŽŸï²•’ëF‚.ŽŽŽŸêGW’ëF‚.ŽŽŽŸäÜ’ëF‚.ŽŽŽŸßpÛ’ëF‚.ŽŽŽŸÚ’ëF‚.ŽŽŽŸÔš_’ëF‚.ŽŽŽŸÏ/!’ëF‚.ŽŽŽŸÉÃã’ëF‚.ŽŽŽŸÄX¥’ëF‚.ŽŽŽŸ¾íg’ëF‚.ŽŽŽŸ¹‚)’ëF‚.ŽŽŽŸ´ë’ëF‚.ŽŽŽŸ®«­’ëF‚.ŽŽŽŸ©@o’ëF‚.ŽŽŽŸ£Õ1’ëF‚.ŽŽŽŸžió’ëF‚.ŽŽŽŸ˜þµ’ëF‚.ŽŽŽŸ““w’ëF‚.ŽŽŽŸŽ(9’ëF‚.ŽŽŽŸˆ¼û’ëF‚.ŽŽŽŸƒQ½’ëF‚.ŽŽŽ ÿ}æ’ëF‚.ŽŽŽ ÿx{A’ëF‚.ŽŽŽ ÿs’ëF‚.ŽŽŽŸäçÊ’t†²tš¸ãyp•Geset‘UUdo“cumen˜tŽŽŽŽŸ‹~K’t†unformatted–UUsource“coGdeŽŽŽŽ ÿpf‘gxprett•¸ãyprin“terŽŽŽŽŸ¶Ø;’ùÎ0language–UUdepGendenš¸ãt“fron˜t“endŽŽŽŽŸÇõ’òœhlanguage–UUindepGendenš¸ãt“bac˜k“endŽŽŽŽŸˆÈ¬’‹Pfparser‘UUusingŽŽŽŽŸ“Ÿ(‘q¥¶prett•¸ãyprin“ting‘UUgrammarŽŽŽŽŽŽŽŽŸ ‘i ”Figure–UU5.1:‘qÇThe“mošGdule“structure“of“mo˜dern“prett•¸ãyprin“tersŽŽŽŸo1‘63×subset–K of“Kn¸ãuth's“command“set“(ÎindentŽ‘Jú²,‘ˆvÎoutdentŽ‘%ïß²,‘ˆvÎfor–ÿ}'c“eŽ‘ÛB²,‘ˆvÎbr–ÿ}'e“aksp“ac“eŽ‘1àå²,‘ˆvÎoptŽ‘©²).Ÿü^ÿ±4ŽŽ‘ ÏV²Roseޤ ‘63×and–tÅW‘ÿ*ªelsh“in“fact“shoš¸ãw“b˜y“example,‘| that“an˜y“language“syn˜tax“can“bGe“transformedŽ¡‘63×inš¸ãto–$Üa“formatted“syn˜tax“that“in“itself“is“capable“of“spGecifying“all“desirable“folds“andŽ¡‘63×cš¸ãhanges–nTof“inden˜tation.‘¼ÃThe“main“precondition“for“this“transformation“is,‘t“that“theŽ¡‘63×starting–~šgrammar“is“conš¸ãtext“free.‘*4None“of“the“ v˜e“basic“commands“is“supGer uous“(asŽ¡‘63×w•¸ãe›M%ha“v“e˜seen˜in˜the˜ rst˜part˜of˜this˜c“hapter)˜so˜w“e˜can˜call˜these˜basic˜commandsŽ¡‘63×the‘UUÎne–ÿ}'c“essary›“çc“ommand˜set‘òز.Ž¡‘E3×The–Ònecessary“command“set“enables“the“ rst“pGoin¸ãt“of“the“basic“actions“of“a“pret-Ž¡‘63×t•¸ãyprin“ter›~Ämen“tioned˜on˜page˜43.‘îThe˜other˜t“w“o˜pGoin“ts˜(additional˜loGcal˜spacing˜ofŽ¡‘63×synš¸ãtactic–•aconstructs;‘µgusing“di eren˜t“fon˜ts)“are“things“that“depGend“on“the“capabili-Ž¡‘63×ties–£Ôof“the“tš¸ãypGesetter“and“are“not“so“m˜uc˜h“a“question“of“the“format“command“set.Ž¡‘63×Thanks–tto“proGcedural“markup,‘¡%as“long“as“the“prett•¸ãyprin“ter›tallo“ws˜us˜to˜insert˜stringsŽ¡‘63×bGet•¸ãw“een›Lšan“y˜t“w“o˜tok“ens˜at˜lexical˜lev“el˜w“e˜are˜able˜to˜handle˜these˜t“w“o˜pGoin“ts˜toGo.Ž¡‘63×Ho•¸ãw“ev“er,‘"öin–^Rubin's“rather“assemš¸ãbler“lik˜e“command“set“[56Ž‘ ,‘"öp.“122]“w˜e“see“that“theŽ¡‘63×necessary–Šcommand“set“still“lacš¸ãks“full“con˜trol“o˜v˜er“v˜ertical“and“horizon˜tal“spacing.Ž¡‘63×One–±“can“argue“o•¸ãv“er–±“what“parts“of“this“issue“bGelong“inš¸ãto“the“domain“of“the“t˜ypGesetterŽ¡‘63×and–Ëwhat“should“bGe“left“to“the“user's“conš¸ãtrol,‘èŽbut“there“surely“is“an“ob˜vious“needŽ¡‘63×to–p‹express“additional“v¸ãertical“separation“in“terms“of“a“simple“format“command.‘ÃjInŽ¡‘63×our–UUcase“this“is“the“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘+ïDzcommand.Ž¡‘E3×The–úZother“command“that“givš¸ães“bGetter“con˜trol“o˜v˜er“horizon˜tal“space“is“Îb‘ÿ}'ackupŽ‘!|š².Ž¡‘63×Both‘ \Îb‘ÿ}'ackupŽ‘%œø²and‘ \Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘-_Õ²can– \bGe“simš¸ãulated“b˜y“sequences“of“commands“from“theŽ¡‘63×necessary–5ùcommand“set.Ÿü^ÿ±5ŽŽ‘ %²So“they“are“not“necessary“but“con•¸ãv“enien“t‘5ùshort-hands.Ž‘63ןʼnff‰¬Ÿ J=‘ "5Ÿý-:¼4ŽŽŽ‘LÜ»The–Z$commands“used“bšÃŽy“Rose“and“W‘ÿJªelsh“are“denoted“b˜y“the“spæsymÃŽb‘ "5Ÿý-:¼5ŽŽŽ‘LÜ»The–#‹sequence“`Ôfor•¥c“eŽ‘Cï»,‘7Ôb¥ackupŽ‘€·»'“is“equal“to“`ÔoutdentŽ‘žö»,‘7Ôfor•¥c“eŽ‘{»,‘7ÔindentŽ‘r~»'“and“`Ôbig‘†Ò‰ff¢$Ž‘(öfor•¥c“eŽ‘õp»'“is“somethingŽŽŽŒ‹/€Š ½\È ýN£8‘'¿¬Ã5.2.‘ÇA–UUSHOR›ÿ*ªT“HISTOR˜Y“OF“PRETTYPRINTING‘v9€²47ŽŽ ˜G ý±ãŽŸÜœrŸóæd‘1  necessary–UUcommand“set“µN‘ Þ4²=Ž’ÄÇ-¸f‘UUÎindentŽ‘ O²,‘UUÎoutdentŽ‘$¼¾²,‘UUÎfor–ÿ}'c“eŽ‘¨!²,‘UUÎbr–ÿ}'e“ak‘‰ffŽ‘®sp“ac“eŽ‘4[ײ,‘UUÎoptŽ‘(ݸgŽŽ¤ ‘-¿¬²con•¸ãv“enien“t–UUcommand“set“µC‘ ~5²=Ž’ÄÇ-µN‘lp¸[–UUf“Îb‘ÿ}'ackupŽ‘ ו²,“Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘+ïǸgŽŽ¡‘6Xì²sucien¸ãt–UUcommand“set“µS‘ Z¦²=Ž’ÄÇ-µC‘ q¸[–UUf“Îc–ÿ}'anc“elŽ‘ná²,“Îno‘‰ffŽ‘®indentŽ‘1_o¸gŽŽŽŽŽŸ!qÇ‘lHܲFigure–UU5.2:‘qÇNaming“of“subsets“of“the“command“set.ŽŽŽŸt‘'¿¬W‘ÿ*ªe–awill“call“them,‘’together“with“the“basic“commands“the“Îc–ÿ}'onvenient›R¡c“ommand˜set‘òز.Ž© :‘6¿¬T¸ãypšGesetting–Nlines“of“co˜de“ ushleft“is“not“a“feature“commonly“needed“in“mo˜dernޤ ‘'¿¬structured–÷âprogramming“languages,‘`„except“in“ÇC²/ÇCŸÿ²++Ž‘†when“using“preproGcessorŽ¡‘'¿¬directiv¸ães–”Ù(and“still“they“do“not“bGelong“to“the“actual“language“itself‘Ç).‘1žThe“Îno‘‰ffŽ‘®indentŽŽ¡‘'¿¬²command–Ü‹caters“for“them“but“it“is“hardly“necessary“in“other“languages,‘ô³where“aloneŽ¡‘'¿¬the–©ãidea“of“excluding“single“lines“from“the“o•¸ãv“erall›©ãinden“tation˜frame˜violates˜all˜rulesŽ¡‘'¿¬of›UUgo•Go“d˜program˜la•¸ãy“out.ަ‘6¿¬Finally–úthe“Îc–ÿ}'anc“elŽ‘% ®²command“doGes“not“add“an¸ãy“striking“new“features“to“theŽ¡‘'¿¬command–Y°set.‘~ØIt“just“alloš¸ãws“more“ exibilit˜y“in“the“placemen˜t“of“format“commandsŽ¡‘'¿¬in–€âthe“output.‘ôoA‘€×wš¸ãell“placed“Îc–ÿ}'anc“elŽ‘"P²command“can“obliterate“a“dozen“rules“of“y˜ourŽ¡‘'¿¬prett•¸ãyprin“ting–‘ grammar“and“thš¸ãus“can“de ate“prett˜yprin˜ting“grammars“v˜ery“m˜uc˜h.Ž¡‘'¿¬So–È£if“yš¸ãou“de ne“suciency“as“incorpGorating“con˜v˜enience“and“ exibilit˜y“w˜e“could“callŽ¡‘'¿¬this–WFwhole“set“of“presenš¸ãted“commands“a“Îsucient–5c‘ÿ}'ommand“set².‘w™This,‘—Áho˜w˜ev˜er,Ž¡‘'¿¬naturally–Çmexcludes“the“opGen“problems“menš¸ãtioned“in“the“next“subsection.‘ÈThe“t˜w˜oŽ¡‘'¿¬subsets–UUof“this“sucien¸ãt“command“set“are“summarized“in“table“5.2.ŽŸI°‘'¿¬Í5.2.5Ž‘Pÿ¬Op`en›€Prett• yprin“ting˜ProblemsŽŸΑ@¿®²\No–ÒÚthere“isn't,‘2;and“there“w¸ãon't“bšGe“[a“metho˜d“of“v¸ãertically“aligningŽ¡‘@¿®statemenš¸ãts–ü×in“ÈCWEB²].“It“is“true“thatÈCWEB‘üÁ²forgets“y˜our“alignmen˜t,‘Šbut“y˜ouŽ¡‘@¿®should–Ç\realise“that“it“also“forgets“Îany“²la•¸ãy“out–Ç\feature“presenš¸ãt“in“y˜ourŽ¡‘@¿®source–Ææ le“(e.g.,‘#Jline“breaks).‘Æ{Apart“from“the“fact“that“it“w¸ãould“bGeŽ¡‘@¿®vš¸ãery–G“hard“to“in˜tegrate“an˜y“alignmen˜t“proGcessing“in˜to“ÈCWEAVE²'s“ordinaryŽ¡‘@¿®parsing–ê@opšGerations,‘zit“is“an“imp˜ossible“task“for“ÈCWEAVE²,“since“it“kno¸ãwsŽ¡‘@¿®nothing– AabGout“the“actual“width“of“iden¸ãti ers“and“other“items.‘“‹So“theŽ¡‘@¿®only–¤µpGossibilitš¸ãy“w˜ould“bGe“to“transmit“alignmen˜t“instructions“to“T‘þU>Ÿ'EŽ‘ãxX,‘ÈbutŽ¡‘@¿®T‘þU>Ÿ'EŽ‘ãxX–‹›t¸ãypšGesets“co˜de“in“paragraph“mo˜de“(breaking“lines“to“the“width“of“theŽ¡‘@¿®page–#§if“necessary),‘-—and“there“is“no“w•¸ãa“y–#§to“mix“that“with“an“alignmen¸ãt."ŽŸt‘@¿®Marc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[63Ž‘ ]ŽŸ8è‘'¿¬If–4³yš¸ãou“ha˜v˜e“ev˜er“tried“to“use“a“prett˜yprin˜ter“for“y˜our“o˜wn“coGde“y˜ou“will“surely“ha˜v˜eŽ¡‘'¿¬come–UUacross“problems“concerning“user“con•¸ãtrol.‘qÇY‘ÿ*ªeh“udai–UUstates,“thatŽ©*®‘@¿®\[.–ªª.“.“]‘¼“it–nDis“not“clear“that“anš¸ãy“automated“inden˜tation“sc˜heme“will“bGeŽ¡‘@¿®adequate,‘hŸas–dÃI‘d¿maš¸ãy“c˜hoGose“di eren˜t“w˜a˜ys“to“la˜y“out“the“same“constructŽ¡‘@¿®in–UUdi erenš¸ãt“parts“of“m˜y“program."‘qÇ[69Ž‘ ,“p.“85]ަ‘'¿¬W‘ÿ*ªo•Go“dman–NOgivš¸ães“an“example“for“this“pGoin˜t“that“he“calls“\adaptiv˜e“com˜bs"“[68Ž‘ ,‘‚êp.“616],Ž¡‘'¿¬where–UUa“long“ÆifŽ‘ ¨²/ÆelsifŽ‘ þ²statemen¸ãt“in“MoGdula-2“is“cited“as:ŽŸ8è‘1¿­ÆifŽ‘;ÊUÎlongexpr‘ÿ}'ession1Ž’„¶ÆthenŽŽ¤ :‘;¿®Îlongstatement1ŽŽ¡‘1¿­ÆelsifŽ‘HÊ«Îexpr2Ž‘e(ÆthenŽ‘"Îstmt2ŽŽ¡‘1¿­ÆelsifŽ‘HÊ«Îlongexpr‘ÿ}'ession3Ž’‘ ÆthenŽŽ¡‘;¿®Îlongstatement3ŽŽ¡‘1¿­ÆelseŽŽ¡‘;¿®Îlongstatement4ŽŽ‘'¿¬Ÿ‘‰ff‰¬Ÿ @»likšÃŽe–ÕX`Ôfor•¥c“eŽ‘Cï»,“Ônulp[lŽ‘âß»,“Ôfor•¥c“eŽ‘G»',“depha˜v˜eŽ¡‘63×commen•¸ãt›êstatemen“ts"˜b“y˜Kaelbling˜[25Ž‘ ]˜and˜that˜b“y˜Grogono˜[17Ž‘ ]˜strongly˜argueŽ¡‘63×that– §at“last“commen¸ãts“should“bGe“treated“equally“as“parts“of“the“language,‘—not“as“anŽ¡‘63×add-on–²Rthat“is“forgotten“at“ rst“pGoin¸ãt“during“compilation.‘ˆ¿Grogono“brings“this“toŽ¡‘63×the–ß)pGoinš¸ãt“b˜y“stating“that“\Commen˜ts“are“second“class“citizens."‘C[17Ž‘ ,‘žp.“80]“TheyŽ¡‘63×are–Rmostly“allo•¸ãw“ed›Ran“ywhere˜in˜the˜source˜coGde˜and˜prett“yprin“ters˜who˜w“an“t˜toŽ¡‘63×preservš¸ãe–àthem“in“the“output“ha˜v˜e“sev˜ere“problems“doing“that“without“destro˜yingŽ¡‘63×the–÷Žprogram's“format,‘ ObšGecause“they“ha•¸ãv“e–÷Žto“b˜e“incorp˜orated“inš¸ãto“the“prett˜yprin˜tingŽ¡‘63×grammar.Ž¡‘E3×There›¤âha•¸ãv“e˜bGeen˜attempts˜to˜do˜this˜in˜a˜structured˜w“a“y‘ÿ*ª,‘È-i.e.˜to˜divide˜commen“tsŽ¡‘63×inš¸ãto–‚{classes“and“to“treat“eac˜h“class“di eren˜tly“[53Ž‘ ,“56Ž›‚},“13Ž˜,“54Ž˜].‘ù8Rose“and“W‘ÿ*ªelshŽ¡‘63×distinguish›ûobGet•¸ãw“een˜pre-˜and˜pGostcommen“ts˜and˜state˜that˜commen“ts˜m“ust˜mo“v“eŽ¡‘63×with–šºthe“synš¸ãtactic“elemen˜ts“that“they“refer“to“[55Ž‘ ,‘¬p.“660].‘AöKaelbling“ev˜en“goGes“asŽ¡‘63×far–k%as“to“demand“\scopGed“commenš¸ãts",‘p™i.e.“commen˜ts“that“explicitly“sho˜w“to“whic˜hŽ¡‘63×part–UUof“the“program“they“bGelong.Ž¡‘E3×All–lNthese“attempts“ha•¸ãv“e–lNthe“same“goal,‘r but“the“problem“of“prett•¸ãyprin“ting‘lNcom-Ž¡‘63×menš¸ãts–÷hwill“only“bGe“solv˜ed,‘íif“they“are“treated“as“an“equal“part“of“a“programmingŽ¡‘63×language–UUand“th¸ãus“are“included“in“the“reference“grammar.Ž‘63× €Cü‰ff‰¬Ÿ J=‘ "5Ÿý-:¼6ŽŽŽ‘LÜ»W‘ÿJªo•Ÿ'EŽ‘ãxX“allo˜wsŽ¡‘@¿®selection–UUof“a“doGcumenš¸ãt“st˜yle“indepGenden˜tly“from“its“con˜ten˜ts)“[...]"ŽŸ""‘@¿®Marc–UUv‘ÿqÇan“Leeu•¸ãw“en‘UU[62Ž‘ ]Ž©ª«‘'¿¬After–"§haš¸ãving“ nally“implemen˜ted“and“tested“the“Pretzel“program“I‘"rha˜v˜e“noticed,Ž¡‘'¿¬that–Îethe“program“doGesn't“do“vš¸ãery“m˜uc˜h“at“all,‘ì©although“it“suits“the“spGeci cationsŽ¡‘'¿¬that–nƒbšGelonged“to“this“pro‘Ž8ject.‘½RT‘ÿ*ªo“enjo¸ãy“b˜eautifully“formatted“source“co˜de“y¸ãou“stillŽ¡‘'¿¬ha•¸ãv“e– ’to“construct“yš¸ãour“prett˜yprin˜ting“grammar.‘5†As“is“seems,‘Ĺthe“w˜ork“of“ ne“tuningŽ¡‘'¿¬sucš¸ãh–¡a“grammar“that“the“prett˜yprin˜ter“is“able“to“handle“the“last“formatting“detailŽ¡‘'¿¬yš¸ãou–øàdesire“is“quite“tedious“and“time-consuming,‘ ^espGecially“if“y˜ou“start“to“build“y˜ourŽ¡‘'¿¬grammar–Uífrom“scratcš¸ãh.‘sBut“after“constructing“suc˜h“a“grammar“for“ÇP‘ÿ ascal“²andŽ¡‘'¿¬applying–S”it“to“a“few“ev•¸ãeryda“y-example–S”ÇP‘ÿ ascal“²source“coGdes,‘SîI‘S“wš¸ãas“astonished“ho˜wŽ¡‘'¿¬easy–y›it“wš¸ãas“to“c˜hange“the“loGoks“of“the“prett˜yprin˜ted“text.‘ÞšI‘yPthink“that“startingŽ¡‘'¿¬with–Låa“formal“grammar“of“yš¸ãour“fa˜v˜ourite“language“and“trying“to“enhance“it“andŽ¡‘'¿¬transform–]Nit“inš¸ãto“a“prett˜yprin˜ting“grammar“is“surely“a“bGetter“w˜a˜y“to“reac˜h“y˜ourŽ¡‘'¿¬goal.‘A’I‘š‡suppšGose–š™that“the“Pretzel“program“could“b˜e“the“righ¸ãt“to˜ol“to“help“y¸ãou“withŽ¡‘'¿¬this‘UUtask.Ž¡‘6¿¬Ho•¸ãw“ev“er,‘áÌsince–ŵonly“few“pšGeople“ha•¸ãv“e–ŵused“Pretzel“un¸ãtil“to˜da¸ãy“there“will“surelyŽ¡‘'¿¬bšGe–Ýma“lot“of“things“p˜eople“miss“when“using“the“program.‘IÏHere“are“a“few“things“I‘ÝOha•¸ãv“eŽ¡‘'¿¬though¸ãt–UUof“already:ަ‘'¿¬ÆAllo®9w›ÕTÈ/*Æ.–êª.“.“È*/˜Æcommen®9ts.ŽŽ’«#d²In–=Iplaces“where“the“user“has“an“empt¸ãy“proGduction“inŽ¡‘@¿®the–òformatted“grammar“ le“or“an“emptš¸ãy“tok˜en“de nition“in“the“formattedŽ¡‘@¿®tokš¸ãen–§| le“ le,‘üit“w˜ould“bGe“nice“to“ha˜v˜e“a“C‘§%lik˜e“commen˜ting“feature“withŽ¡‘@¿®opGening–Ûand“closing“delimiters.‘KYThe“`È//²'“commenš¸ãt“delimiter“isn't“nice“if“y˜ouŽ¡‘@¿®w•¸ãan“t–UUto“add“an“attribute“de nition“to“an“empt¸ãy“proGduction.Ž©DD‘'¿¬ÆCop•®9y‘ÕTcommen“ts.ŽŽ’€XͲIt– ³surely“wš¸ãould“mak˜e“the“generated“ ex“and“Bison“ les“moreŽ¡‘@¿®readable,‘ªUif–™UPretzel“wš¸ãould“cop˜y“the“commen˜ts“from“the“formatted“tok˜en“andŽ¡‘@¿®the–UUformatted“grammar“ les“in¸ãto“them.ަ‘'¿¬ÆGenerate–ÕTÈ%token“Æde nitions.ŽŽ’¹ϲIf–¥0one“w¸ãould“impGose“the“restriction“to“use“only“up-Ž¡‘@¿®pGercase–×^idenš¸ãti ers“as“terminal“tok˜en“names“Pretzel“could“automalically“gener-Ž¡‘@¿®ate–Åthe“list“of“È%token“²de nitions“needed“to“iden¸ãtify“terminals“in“the“formattedŽ¡‘@¿®grammar‘UU le.ŽŽŸK’×lx49ŽŽŒ‹2¾ ½\È ýN£8‘63ײ50’Êà¤ÃCHAPTER–UU6.‘ÇFUTURE“W¸ãORKŽŽ ˜G ý„‘63ׯChange›ÕTprett•®9yprin“ting˜grammar˜format.ŽŽ’²It–Èw¸ãould“bšGe“nice“to“b˜e“able“to“insertŽ© ‘O3Ùformat–UUcommands“directly“inš¸ãto“the“grammar“rules,“lik˜e“for“example“in:ޤ‘Y3ÚÈWHILE–?ýexpr“DO“ÎindentŽ‘&ÊôÈstmt“ÎoutdentŽ‘+çcfor–ÿ}'c“eŽ‘Fz,¸ŽŽŽ‘L–¢!“ÈstmtŽ¡‘O3Ù²This–yÌis“a“pGoinš¸ãt“that“e ects“fundamen˜tals“of“the“Îbuild‘‰ffŽ‘®pp‘ÿ}'arseŽ‘;Ït²function.‘ß,Otherަ‘O3Ùparts–ìof“Pretzel“are“not“in•¸ãv“olv“ed.‘ÎŒThis–ìis“a“cš¸ãhange“that“w˜ould“bšGe“go˜o˜d“forަ‘O3Ùnew–UUusers,“since“this“w•¸ãa“y–UUof“spGecifying“the“grammar“is“m•¸ãuc“h–UUmore“in•¸ãtuitiv“e.ޤ‘63ׯInclude–ÕT les“for“grammars.ŽŽ’²As–8ãparts“of“prett•¸ãyprin“ting–8ãgrammars“oGccur“frequen¸ãtlyަ‘O3Ùin–™Lmanš¸ãy“di eren˜t“programming“languages“(suc˜h“as“the“formatting“of“expres-ަ‘O3Ùsions)–Úµit“w¸ãould“bšGe“nice“to“b˜e“able“to“include“ les“that“con¸ãtain“these“de nitionsަ‘O3Ùwith–!üa“simple“command“in“the“formatted“tok¸ãen“and“formatted“grammar“ les.ަ‘O3ÙOn–éña“more“abstract“lev¸ãel“one“could“think“of“a“notion“of“moGdules“of“grammars,ަ‘O3Ùi.e.–ANparts“of“a“grammar“that“can“bšGe“called“with“argumen¸ãts“to“suit“lo˜cal“demandsަ‘O3Ù(\grammar–KÞtemplates"?).‘nŸBut“it“is“still“an“unansw¸ãered“question“whether“thisަ‘O3Ùis–Çfpractical,‘ãêbšGecause“of“the“lac¸ãk“of“metho˜d“to“sp˜ecify“the“inš¸ãterface“of“suc˜h“aަ‘O3ÙmoGdule.Ž¡‘63ׯEnhance–ÕTÈnoweb“ÆsuppQÇort.ŽŽ’±üå²This–ËÑincludes“managing“mš¸ãultiple“prett˜yprin˜ting“ ltersަ‘O3Ùand–cMautomatically“selecting“a“ lter“for“the“righš¸ãt“language“(if“y˜ou“mix“languagesަ‘O3Ùin–;¼Ènoweb“² les).‘i?The“Ènoweb“²suppGort“seems“the“place“where“the“most“w¸ãork“canަ‘O3ÙbGe–UUdone“to“get“a“practical“system.ŽŸ‘63×Suggestions–UUare“alw•¸ãa“ys‘UUw“elcome.ŽŽŽŒ‹3Ë× ½\È ýN£8 ˜G ýÏq%‘'¿¬ÊChapter‘Ç 7ŽŸ2q%‘'¿¬ÅReferenceŽŸ4q$‘@¿®²\I‘ýGused–ýrto“think“that“prett•¸ãyprin“ting›ýrw“as˜the˜cats˜meo“w,‘'ybut˜after˜bGe-ޤ ‘@¿®coming–‹a“bit“accustomed“to“Ènoweb“²I›ŠÂ nd“that“a“ÈCWEB˜²prin¸ãtout“loGoksŽ¡‘@¿®somewhat–UUlik¸ãe“gibbGerish."ŽŸâI‘@¿®Barry›UUSc•¸ãh“w“artz˜[58Ž‘ ]ŽŸÄ“‘'¿¬This–×”cš¸ãhapter“con˜tains“a“complete“and“detailed“reference“of“the“Pretzel“system.‘GÜThisŽ¡‘'¿¬is–¬Ìinformation“that“mostly“is“also“conš¸ãtained“in“the“man˜ual“pages“Èpretzel(1)“²andŽ¡‘'¿¬Èpretzel-it(1)².ŽŸ#j ‘'¿¬Ì7.1Ž‘L¦The–ffConcept“of“PretzelŽŸ¹­‘'¿¬²The–Féconcept“of“Pretzel“is“visualized“in“ gure“7.1.‘F‚F‘ÿ*ªrom“a“formal“formatting“de-Ž¡‘'¿¬scription–ðÌof“a“programming“language“µP‘c²,‘çPretzel“generates“a“prett•¸ãyprin“ting‘ðÌfunctionŽ¡‘'¿¬that–ûcan“bšGe“used“to“prett•¸ãyprin“t–ûsource“co˜de“in“µP‘c².‘w¸T‘ÿ*ªo“get“the“actual“prett•¸ãyprin“t-Ž¡‘'¿¬ing–Òprogram,‘Ÿ±yš¸ãou“only“ha˜v˜e“to“supply“a“main“program“(or“use“the“one“that“comesŽ¡‘'¿¬with–¾ýPretzel).‘®¾If“the“w•¸ãa“y–¾ýof“prett•¸ãyprin“ting–¾ýneeds“to“bGe“c¸ãhanged,‘fthe“user“onlyŽ¡‘'¿¬needs–éto“c¸ãhange“formal“parts“in“the“input“and“use“Pretzel“again“to“get“an“enhancedŽ¡‘'¿¬prett•¸ãyprin“ter.ŽŸ q%‘6¿¬Figure–&ö7.2“on“page“53“shoš¸ãws“the“generating“proGcess“in“sligh˜tly“more“detail.‘bRTheŽ¡‘'¿¬ gure–•shoš¸ãws“that“the“program“Pretzel“doGesn't“generate“a“prett˜yprin˜ter“immediately;Ž¡‘'¿¬what–óyit“došGes“is“to“pro˜duce“co˜de“that“can“b˜e“turned“inš¸ãto“a“ÇCŸÿ²++Ž‘µprett˜yprin˜ting“classŽ¡‘'¿¬with–UUthe“help“of“t•¸ãw“o‘UUtoGols:ŽŸSn‘'¿¬Æ exŽŽ‘>zQ²A–UUPOSIX.2“complian¸ãt“lexical“analyser“generator.ŽŸÄ’‘'¿¬ÆBisonŽŽ‘HÌn²A‘uÅPOSIX.2–uÍcomplianš¸ãt“parser“generator.‘Ó/The“v˜ersion“used“with“Pretzel“hasŽ¡‘@¿®to–UUproGduce“ÇCŸÿ²++Ž‘ã‘complian¸ãt“source.Ž ‡XÚŸÞ9ŸÕiè’¼|pretzelŽŽŽ’©æŸï¾F‰feAÓ²ŸAº„AºfeŸ÷ß#Ž‘Aè„AºfeŽžfe‰feAÓ²ŽŽŽ’ÇçŸêS„ ÝfeŽ’ÈPŸêS¬?ŽŽ’”ŸƒŸøE‰„ÌÌAº‘öž™šóäO£ linew10­-ŽŽ’î ŸøE‰„Ì̬ø‘öž™š-ŽŽ’´¼’ŸÌ…3‰fe)qŸAº„AºfeŸ÷ß#Ž‘(¤Q„AºfeŽžfe‰fe)qŽŽŽ’ÇçŸÇõ„ Ö|feŽ’ÈPŸÇõ¬?ŽŽŸ·œ’£,[²formal‘UUdescriptionŽŽŽŸø¢û’®“yprett•¸ãyprin“terŽŽŽŸú”‘ÉT‘ÿ*ªextŽŽŽŸð‚’¿óprett•¸ãyprin“tedŽŽŽ’¢ðtextŽŽŽŽŽŽŽŸ ’—Figure–UU7.1:‘qÇThe“concept“of“Pretzel.ŽŽŽŽŸK’×lx51ŽŽŒ‹4Óc ½\È ýN£8‘63ײ52’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63ײUsers–üthat“are“already“familiar“with“the“basics“of“bšGoth“to˜ols“will“ nd“it“easier“toޤ ‘63×read–)othe“folloš¸ãwing“text“bGecause“the“w˜a˜y“of“spGecifying“input“to“Pretzel“is“quite“closeŽ¡‘63×to–mthe“w•¸ãa“ys–mused“bš¸ãy“them.‘¸ýHo˜w˜ev˜er,‘sthis“text“aims“at“pGeople“who“don't“ha˜v˜e“suc˜hŽ¡‘63×knoš¸ãwledge–UUand“will“explain“ev˜erything“that“is“necessary‘ÿ*ª.Ž© ˆ‡‘E3×Also–UUvisible“from“this“ gure“is“that“Pretzel“creates“t•¸ãw“o‘UUthings:ŽŸ"‘E3ظŽŽŽ‘O3Ù²A›UUprett•¸ãyprin“ting˜scanner˜class˜andŽŸ"‘E3ظŽŽŽ‘O3Ù²a›UUprett•¸ãyprin“ting˜parser˜class˜(con“taining˜the˜actual˜prett“yprin“ter).ŽŸ"‘E3×The›áprett•¸ãyprin“ting˜parser˜is˜the˜actual˜prett“yprin“ter˜function˜that˜y“ou˜normallyŽ¡‘63×w•¸ãan“t–³to“get“when“using“Pretzel.‘ŠÈThe“prett•¸ãyprin“ting–³scanner“is“used“b¸ãy“the“parserŽ¡‘63×and–!utakš¸ães“care“of“the“tok˜en“formatting.‘Ö'Both“parts“are“separate“moGdules“with“aŽ¡‘63×wš¸ãell–.gde ned“in˜terface“and“can“bGe“used“individually‘ÿ*ª.‘dÍHence,‘60y˜ou“can“write“y˜our“o˜wnŽ¡‘63×scanner–¬|or“parser“if“yš¸ãou“really“need“features“that“the“ones“proGduced“b˜y“Pretzel“don'tŽ¡‘63×ha•¸ãv“e.ŽŸÒ‘63×Í7.1.1Ž‘_s×The–€Input“FilesŽŸsj‘63ײThe–Ãåwš¸ãord“\prett˜y"“is“v˜ery“sub‘Ž8jectiv˜e“and“so“programming“language“source“coGde“canŽ¡‘63×bGe–#prinš¸ãted“in“a“\prett˜y"“kind“of“fashion“in“almost“in nitely“man˜y“w˜a˜ys,‘ž×accordingŽ¡‘63×to–X³the“taste“and“preferences“of“the“user.‘{âIf“the“task“of“prett•¸ãyprin“ting–X³is“handedŽ¡‘63×o•¸ãv“er–›Œto“the“computer,‘­the“user“mš¸ãust“spGecify“in“detail“all“of“his“wishes“to˜w˜ards“theŽ¡‘63×appGearance–UUof“the“output“of“the“prett•¸ãyprin“ter.ަ‘E3×T‘ÿ*ªo–%©generate“a“prett•¸ãyprin“ter,‘Y¾Pretzel–%©needs“t•¸ãw“o–%©descriptions“that“it“expGects“toŽ¡‘63× nd–UUin“t•¸ãw“o›UUdi eren“t˜ les:ŽŸ"‘63ׯA–ÕTformatted“tok®9en“ le.ŽŽ’®Ú̲This–º le“should“con¸ãtain“all“information“concerning“theŽ¡‘O3Ùindividual–UUformatting“of“tokš¸ãens“(i.e.“iden˜ti ers,“reserv˜ed“w˜ords,“etc.).ŽŸ"‘63ׯA–ÕTformatted“grammar“ le.ŽŽ’ÀÊIJThis–’4 le“should“conš¸ãtain“a“prett˜yprin˜ting“grammar,Ž¡‘O3Ùi.e.–­a“con¸ãtext“free“grammar“enhanced“with“formatting“commands.‘_äThis“infor-Ž¡‘O3Ùmation–’yis“necessary“to“handle“the“more“global“aspGects“of“prett•¸ãyprin“ting‘’ythatŽ¡‘O3Ùneed–m›information“abGout“the“language“conš¸ãtext“(i.e.“inden˜tation,‘³¬line“breaks,Ž¡‘O3Ùetc.).ŽŸ"‘63×The–Ëdname“of“the“ rst“ le“migh¸ãt“bšGe“a“little“misleading,‘(çsince“it“do˜esn't“con¸ãtainŽ¡‘63×formatted–¸Btokš¸ãens.‘=lInstead“it“tells“y˜ou“what“y˜ou“will“get“from“the“de nitions“therein.Ž¡‘63×A‘Jùname–K=likš¸ãe“\tok˜en“formatting“ le"“migh˜t“ha˜v˜e“bšGeen“a“little“b˜etter,‘€ubut“the“similarit¸ãyŽ¡‘63×in–—¨names“bšGet•¸ãw“een–—¨the“t•¸ãw“o–—¨input“ les“sounded“go˜o˜d“and“seemed“to“outpla¸ãy“this“smallŽ¡‘63×inconsistency‘ÿ*ª.ަ‘E3×The–HVspšGecial“formats“of“these“t•¸ãw“o–HV les“are“describ˜ed“later“in“section“7.2.‘JÉTheŽ¡‘63×in¸ãterface–UUto“the“generated“Pretzel“classes“is“describGed“in“detail“in“section“3.2.ŽŸ#æ‘63×Ì7.2Ž‘[:The–ffF‘þ¦format“of“the“Input“FilesŽŸå1‘63ײNo•¸ãw›¶w“e˜turn˜to˜a˜vital˜thing˜for˜the˜user˜of˜Pretzel:‘",The˜format˜of˜the˜Pretzel˜inputŽ¡‘63× les.‘l³Here–Fthe“user“has“to“put“a“formal“description“of“the“underlying“programmingŽ¡‘63×language–ôand“(with“the“help“of“format“commands)“state“ho¸ãw“its“text“should“bGeŽ¡‘63×formatted.ަ‘E3×W‘ÿ*ªe›×'ha•¸ãv“e˜seen˜that˜Pretzel˜tak“es˜t“w“o˜input˜ les:‘ujThe˜formatted˜tok“en˜ le˜andŽ¡‘63×the–¤“formatted“grammar“ le.‘6ÜW‘ÿ*ªe“suggest“to“use“the“sux“`È.ft²'“for“a“formatted“tok¸ãenŽ¡‘63× le–UUand“`È.fg²'“for“a“formatted“grammar“ le.ŽŽŽŒ‹5Üù ½\È ýN£8‘'¿¬Ã7.2.‘ÇTHE–UUF¸ãORMA‘ÿ*ªT“OF“THE“INPUT“FILES’”'¹²53ŽŽ ˜G þjÄ0ŸÞ9’õΟŽ3ê„ ƒtfeŽ’ )ŸŽ3ê¬?ŽŽ’õΟ±lý„b—feŽ’ )Ÿ±lý?ŽŽ’õΟ÷ß#„(¤QfeŽ’ )Ÿ÷ß#?ŽŽ ÿBV†’Zògrammar‘UU leŽŽŽŽ ÿhE8’¨ýBison‘UUsourceŽŽŽŽŸ–TÇ’ >RC++‘UUcoGdeŽŽŽŽŸ¼Cy’pprett•¸ãyprin“tingŽŽŽŽ’6ëprett•¸ãyprin“terŽŽŽŽ ÿR˜@’%”>Îpr‘ÿ}'etzelŽŽŽŽŸ€§Ï’%”>BisonŽŽŽŽŸ©L ’%”>CCŽŽŽŽ ÿ7€ ’ žQ²formattedŽŽŽŽŸÇõ’ÅpparserŽŽŽŽŸ‹~K’ÍáʱcommonŽŽŽŽŸ“Ÿ(’ÆŽtokÈãen‘±ÈheaderŽŽŽŽ’õΠÿ]n¼„b—feŽ’ ) ÿ]n¼¬?ŽŽ’˜|À ÿ`$[„6feŽ’˜¯ò ÿ`$[?ŽŽŸÇõ’ˆA·²scannerŽŽŽŽ’˜|ÀŸŽ3ê„ ƒtfeŽ’˜¯òŸŽ3ê¬?ŽŽ’˜|ÀŸ´"œ„b—feŽ’˜¯òŸ´"œ?ŽŽ’˜|ÀŸäçÊ„6feŽŽ’˜¯òŸåü„fdX1‘öžÌÎ-ŽŽ ÿuÅ¢’ÈѰ.ŽŽŽ ÿuÅ¢’þ¨.ŽŽŽ ÿuÅ¢’ 4.ŽŽŽ ÿuÅ¢’jV.ŽŽŽ ÿuÅ¢’ú -.ŽŽŽ ÿuÅ¢’òÖ.ŽŽŽ ÿuÅ¢’ë Û.ŽŽŽ ÿuÅ¢’ãA².ŽŽŽ ÿuÅ¢’Ûw‰.ŽŽŽ ÿuÅ¢’Ûwˆ.ŽŽŽ ÿ|‹¯’Ûwˆ.ŽŽŽŸƒQ¼’Ûwˆ.ŽŽŽŸ˜þµ’Ûwˆ.ŽŽŽŸžió’Ûwˆ.ŽŽŽ’ž0Ÿžu¤¬ŽŽŸžió’Ûwˆ°.ŽŽŽŸžió’Ó­_.ŽŽŽŸžió’Ëã6.ŽŽŽŸžió’Ä .ŽŽŽŸžió’¼Nä.ŽŽŽŸžió’´„».ŽŽŽŸži󒬺’.ŽŽŽŸžió’¤ði.ŽŽŽ ÿBV†’„¯ï²tok¸ãen‘UU leŽŽŽŽ ÿhE8’ºš ex‘UUsourceŽŽŽŽŸ–TÇ’ÅDC++‘UUcoGdeŽŽŽŽŸ¼Cy‘y÷ prett•¸ãyprin“tingŽŽŽŽ ÿR˜@’›e‘Îpr‘ÿ}'etzelŽŽŽŽŸ€§Ï’›e‘ exŽŽŽŽŸ©L ’ž0CCŽŽŽŽŸâ2+’ÁTC²is–UUcalled“b¸ãyŽŽŽŽ ÿ7€ ’ƒ%CformattedŽŽŽŽŽŽŽŽŸ ‘9/öFigure–UU7.2:‘qÇThe“currenš¸ãt“proGcess“of“generating“a“prett˜yprin˜ter“with“Pretzel.ŽŽŽŸ£‘'¿¬Í7.2.1Ž‘Pÿ¬The–€F›þàormatted“T˜ok en“FileŽŸ„Ï‘'¿¬²The–­`formatted“tokš¸ãen“ le“con˜tains“a“list“of“tok˜en“de nitions“with“their“correspGondingޤ ‘'¿¬\prett•¸ãyprin“ted"–+iform.‘cÎThe“prett•¸ãyprin“ted–+iform“of“a“tok¸ãen“will“bGe“called“an“ÎattributeŽ¡‘'¿¬²or–UUa“Îtr‘ÿ}'anslation².ޤ Q‘6¿¬The–UUgeneral“outline“of“the“formatted“tok¸ãen“ le“isŽ©!E‘1¿­Îde–ÿ}'clar“ationsŽŽ¡‘1¿­È%%Ž¡‘1¿­Îtoken‘“çde nitionsŽŽŸô‘'¿¬²Normally‘ÿ*ª,‘vothe›oÑÎde–ÿ}'clar“ations˜²part˜is˜empt¸ãy–ÿ*ª.‘Á:Y“ou˜can˜put˜a˜general˜description˜of˜theޤ ‘'¿¬ le–-Phere“(as“a“ÇC“²commenš¸ãt)“and“rede nitions“of“the“default“in˜terface“go“here“as“w˜ellŽ¡‘'¿¬(see–UUsection“3.2“for“more).ŽŸ Q‘6¿¬The–{|Îtoken‘Ë}de nitions“²section“of“the“formatted“tokš¸ãen“ le“con˜tains“a“series“of“tok˜enŽ¡‘'¿¬de nitions–UUof“the“form:ަ‘1¿­Îp‘ÿ}'atternŽ‘eOctokenŽ’‘U)¸fÎattributeŽ‘%­Ë¸gŽŸô‘'¿¬²The–{ïÎp‘ÿ}'attern“²mš¸ãust“bGe“a“v‘ÿqÇalid“regular“expression“(in“terms“of“Èflex²)“and“m˜ust“bGeŽ¡‘'¿¬unindenš¸ãted.‘ašThe–OñÎtoken“²spGeci es“the“sym˜bGolic“name“of“the“tok˜en“for“the“patternŽ¡‘'¿¬and–õ²bGegins“at“the“ rst“non-whitespace“cš¸ãharacter“after“the“pattern.‘QæThe“tok˜en“nameŽ¡‘'¿¬mš¸ãust–)|bGe“a“legal“name“for“an“iden˜ti er“in“ÇP‘ÿ ascal“²notation“and“Îmust–kb›ÿ}'e“al‘‚Øl“in“upp˜erŽ¡‘'¿¬c‘ÿ}'ase².‘qÇ(Underlines–UUare“allo•¸ãw“ed–UUbut“not“at“the“bGeginning“of“a“w¸ãord.)Ž© Q‘6¿¬The–°Îattribute“²for“this“tokš¸ãen,‘Ç^that“is“it's“prett˜yprin˜ted“form,‘Ç^consists“of“all“textŽ¡‘'¿¬bšGet•¸ãw“een–Øthe“t•¸ãw“o–Øcurling“brac•¸ãk“ets–Ø`¸f²'“and“`¸g²'.‘H/A¸ãttributes“can“b˜e“either“simple“stringsŽ¡‘'¿¬(surrounded–Šcbš¸ãy“double“quotes)“or“format“commands“(lik˜e“Îfor–ÿ}'c“eŽ‘Ý/²,‘—¦ÎindentŽ‘â ²)“or“a“com-Ž¡‘'¿¬bination–¨kof“bGoth“joined“together“bš¸ãy“an“optional“`È+²'“sign.‘kA˜ttribute“de nitions“canŽ¡‘'¿¬co•¸ãv“er›`ƒsev“eral˜lines˜and˜the˜starting˜`¸f²'˜needn't˜stand˜on˜the˜same˜line˜as˜the˜tok“enŽ¡‘'¿¬de nition;‘tŒho•¸ãw“ev“er›Ïsubsequen“t˜lines˜m“ust˜bGe˜inden“ted˜with˜at˜least˜one˜blank˜orŽ¡‘'¿¬one–ÖÁtab.‘ö Aš¸ãttributes“can“also“con˜tain“ÇC‘Ö ²coGde.‘ö See“section“3.1“or“the“man˜ual“pageŽ¡‘'¿¬Èpretzel(1)–UU²for“details.ަ‘6¿¬If–0yš¸ãou“de ne“strings“as“part“of“an“attribute“de nition,‘7zy˜ou“ha˜v˜e“to“spGecify“themŽ¡‘'¿¬in–WÇa“ÇC“²kind“of“fashion,‘˜ci.e.“y¸ãou“can“insert“newlines“and“tabs“with“`È\n²'“and“`È\t²'.ŽŽŽŒ‹6ëÿ ½\È ýN£8‘63ײ54’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63ײBut–ïòif“yš¸ãou“w˜an˜t“to“insert“a“bac˜kslash“in˜to“a“string,‘V™y˜ou“m˜ustn't“forget“to“putޤ ‘63×t•¸ãw“o›ÀÀbac“kslashes˜(`È\\²')˜in“to˜the˜input˜ le.‘´This˜is˜espGecially˜notew“orth“y˜if˜y“ou˜areŽ¡‘63×using–¾PT‘þU>Ÿ'EŽ›ãxX“as“t¸ãyp•Gesetter,‘ØŽb“ecause–¾PT‘þU>Ÿ'EŽ˜X“uses“a“bacš¸ãkslash“as“a“pre x“for“t˜ypGesettingŽ¡‘63×commands.Ž© ™ë‘E3×If–rthe“de nition“of“the“attribute“is“omitted“Pretzel“creates“an“attribute“for“thisŽ¡‘63×pattern–cWbš¸ãy“default.‘›ÌThe“default“attribute“consists“of“the“string“con˜taining“the“textŽ¡‘63×matc•¸ãhed›UUb“y˜the˜correspGonding˜pattern.ަ‘E3×The–&duser“himself“maš¸ãy“also“refer“to“the“matc˜hed“text“b˜y“using“the“sequence“`È**²'.Ž¡‘63×Th¸ãusŽ©ÍÁ‘@³ÑÈ"foo"‘$¿ëBARŽ¡‘@³Ñ"foo"‘$¿ëBAR‘?ñ{–?ý**“}Ž¡‘@³Ñ"foo"‘$¿ëBAR‘?ñ{–?ý"foo"“}ަ‘63ײall›UUha•¸ãv“e˜the˜same˜meaning.Ž© ™ë‘E3×Y‘ÿ*ªou–7Çcan“use“a“`È|²'“sign“as“a“tokš¸ãen“name;‘©this“signals“that“the“curren˜t“regularŽ¡‘63×expression–h?has“the“same“tokš¸ãen“name“(and“also“the“same“attribute)“as“the“tok˜enŽ¡‘63×spGeci ed–g³in“the“folloš¸ãwing“line“(empt˜y“lines“are“ignored).‘¨àAn“attribute“de nitionŽ¡‘63×bGehind–jwa“`È|²'“is“illegal.‘±.Ho•¸ãw“ev“er›jwy“ou˜ma“y˜spGecify˜regular˜expressions˜with˜neither˜aŽ¡‘63×tokš¸ãen–UUname“nor“an“attribute“to“giv˜e“a“default“rule“or“to“eat“up“whitespace.ަ‘E3×The–¯(folloš¸ãwing“examples“are“all“legal“tok˜en“de nitions“(and“please“note“the“dotŽ¡‘63×in–UUthe“v¸ãery“last“line):Ž©g¬‘@³ÑÈ[0-9]‘9¿ßDIGITŽ¡¡‘@³Ñ"{"‘D?ÙOPEN‘9¿ß{–?ý"\\{"“indent“force“}Ž¡¡‘@³Ñ[a-z][a-z0-9]*‘ úID‘D?Ù{–?ý"{\\it“"“+“**“+“"}"“}Ž¡¡‘@³Ñ"function"‘î|Ž¡‘@³Ñ"procedure"–?ñPROC_INTRO“{–?ýbig_force“**“}Ž¡¡‘@³Ñ[\t\‘?ý\n]‘)ÿè|Ž¡‘@³Ñ.ަ‘E3ײThe–U¬declarations“and“the“tokš¸ãen“de nitions“m˜ust“bGe“separated“b˜y“a“line“con˜tainingŽ¡‘63×only–UUthe“t•¸ãw“o›UUc“haracters˜È%%².‘qÇSo˜the˜shortest˜pGossible˜formatted˜tok“en˜ le˜isޤÍÁ‘EóÎÈ%%Ž¡‘63ײbut–UUthis“došGesn't“seem“of“an¸ãy“use,“do˜es“it?ŽŸ.Õ‘63×Í7.2.2Ž‘_s×The–€F‘þàormatted“Grammar“FileŽŸ“È‘63ײIn–Þthe“formatted“grammar“ le“the“user“encoGdes“the“general“prett•¸ãyprin“ting‘Þgrammarޤ ‘63×for–w&the“programming“language.‘×9This“is“done“bš¸ãy“spGecifying“a“con˜text“free“grammarŽ¡‘63×of–WIthe“language“and“b¸ãy“adding“information“abGout“the“creation“of“new“attributes“inŽ¡‘63×ev¸ãery‘UUrule.Ž© ™ë‘E3×The–Çùformatted“grammar“ le“is“the“second“and“last“input“to“the“Pretzel“program.Ž¡‘63×Its–UUgeneral“outline“loGoks“lik¸ãe“this:ŽŸ—‘@3ØÎtoken‘“çde–ÿ}'clar“ationsŽŽ¦‘@3ØÈ%%ަ‘@3ØÎgr‘ÿ}'ammar‘“çrulesŽŽŽŽŒ‹7û  ½\È ýN£8‘'¿¬Ã7.2.‘ÇTHE–UUF¸ãORMA‘ÿ*ªT“OF“THE“INPUT“FILES’”'¹²55ŽŽ ˜G ý„‘6¿¬The›»æÎtoken‘¿de–ÿ}'clar“ations˜²section˜ma•¸ãy˜bGe˜empt“y˜and˜the˜separator˜bGet“w“een˜the˜t“w“oޤ ‘'¿¬parts–¯of“the“ le“(È%%²)“mš¸ãust“appGear“uninden˜ted“on“a“single“line“b˜y“itself.‘Before“w˜eŽ¡‘'¿¬lošGok–UUat“these“declarations,“let's“ha•¸ãv“e–UUa“lo˜ok“at“the“grammar“rules.Ž¡‘6¿¬The–ÓÎgr‘ÿ}'ammar‘Kprules“²section“conš¸ãtains“the“collection“of“rules“of“the“con˜text“freeŽ¡‘'¿¬grammar–ýAthat“can“bšGe“accompanied“b¸ãy“an“attribute“de nition.‘iŒA‘ýrule“is“sp˜eci edŽ¡‘'¿¬bš¸ãy–œûstating“the“resulting“tok˜en,‘îåa“colon“and“then“the“series“of“tok˜ens“whic˜h“willŽ¡‘'¿¬bGe–öreduced“bš¸ãy“this“rule.‘T#The“rule“is“ended“b˜y“a“semicolon.‘T#A‘õõbloGc˜k“de nition“inŽ¡‘'¿¬ÇP‘ÿ ascal–UU²for“example“mighš¸ãt“loGok“lik˜e“this:Ž©33‘2?¦Èblock–?ý:“BEGIN“stmt_list“ENDŽ¡‘2?¦;ަ‘6¿¬²F‘ÿ*ªolloš¸ãwing–þÚthe“tok˜en“list“on“the“righ˜t“side“of“the“colon“can“bGe“an“attribute“de ni-Ž¡‘'¿¬tion;‘Sthis–Qøde nition“states,‘R¤hoš¸ãw“the“translation“of“the“proGduced“sym˜bGol“is“obtainedŽ¡‘'¿¬from–UUthe“tokš¸ãens“on“the“righ˜t“side“of“the“rule.Ž¡‘6¿¬An–fDattribute“de nition“is“brac•¸ãk“eted–fDamidst“curling“brac•¸ãk“ets–fD`¸f²'“and“`¸g²'“and“canŽ¡‘'¿¬again–D}consist“of“strings“(in“double“quotes)“and“format“commands“or“bGoth“joinedŽ¡‘'¿¬together–mwith“`È+²'.‘[%But“here“yš¸ãou“can“also“refer“to“the“attributes“of“the“tok˜ens“on“theŽ¡‘'¿¬righš¸ãt–¸Kside“of“the“rule.‘š©This“is“done“in“a“sligh˜tly“a˜wkw˜ard“notation“with“a“n˜um˜bGerŽ¡‘'¿¬that–›“is“preceded“with“a“`È$²'“dollar“sign.‘3ÜThe“n•¸ãum“bšGers–›“refer“to“the“order“of“app˜earanceŽ¡‘'¿¬of–…Šthe“symš¸ãbGols“on“the“righ˜t“side“of“the“rule.‘fSo“`È$1²'“refers“to“the“ rst“tok˜en“of“theŽ¡‘'¿¬rule,–UU`È$2²'“to“the“second,“.–ªª.“.Ž¡‘6¿¬Again–¶attribute“de nitions“are“allo•¸ãw“ed–¶to“span“sevš¸ãeral“lines“and“strings“m˜ust“bGeŽ¡‘'¿¬spšGeci ed–UUin“ÇC“²manner.‘qÇThey“can“also“con¸ãtain“ÇC“²co˜de“as“describ˜ed“in“section“3.1.Ž¡‘6¿¬F‘ÿ*ªor–JØexample,‘ˆ8here“again“is“the“pšGossible“de nition“of“a“blo˜cš¸ãk“in“ÇP‘ÿ ascal²,‘ˆ8no˜wŽ¡‘'¿¬with–UUan“example“attribute“de nition:ަ‘2?¦Èblock–?ý:“BEGIN“stmt_list“END‘¿÷{“$1“+“$2“+“force“+“$3“}Ž¡‘2?¦;ަ‘6¿¬²The–)æattribute“of“a“Èblock“²will“therefore“consist“of“the“attributes“of“the“ÈBEGINŽ¡‘'¿¬²and–¸}Èstmt‘¡E‰ff&fŽ‘Ç«list“²tok¸ãens,‘ÑGjoined“together“with“a“Îfor–ÿ}'c“eŽ‘ÃÆ²command“and“the“translationŽ¡‘'¿¬of–UUthe“ÈEND“²tok¸ãen.Ž¡‘6¿¬The–Vžattribute“de nition“maš¸ãy“bGe“omitted.‘u£If“this“is“so,‘–ðPretzelwill“b˜y“defaultŽ¡‘'¿¬form–6Ûthe“attribute“of“the“prošGduced“sym¸ãb˜ol“from“the“simple“concatenation“of“theŽ¡‘'¿¬attributes–UUon“the“righ¸ãt“side“of“the“rule.‘qÇF‘ÿ*ªor“instanceަ‘2?¦Èstmt–?ý:“block“SEMIŽ¡‘2?¦;ަ‘'¿¬²means–UUthe“same“as:ަ‘2?¦Èstmt–?ý:“block“SEMI‘$¿ë{“$1“+“$2“}Ž¡‘2?¦;ަ‘6¿¬²Of–`ücourse“yš¸ãou“ma˜y“also“ha˜v˜e“empt˜y“righ˜t“sides“of“a“rule“(to“proGduce“things“outŽ¡‘'¿¬of–£ßnothing)“or“simply“concatenate“t•¸ãw“o–£ßor“more“rules“resulting“in“the“same“sym¸ãbGolŽ¡‘'¿¬with–UUa“`È|²'.‘qÇSo“the“follo¸ãwing“are“legal“rules:ަ‘2?¦Èstmt_list‘¿÷:‘s¾{–?ýforce“}Ž¡‘q?‚|–?ýstmt_list“stmt“SEMI‘ ú{“$1“$2“$3“force“}Ž¡‘2?¦;ަ‘6¿¬²T‘ÿ*ªo–yend“this“subsection,‘,wš¸ãe“ha˜v˜e“to“return“to“the“Îtoken‘2Ede–ÿ}'clar“ations–y²section“ofŽ¡‘'¿¬the–ø×formatted“grammar“ le.‘RóHere“wš¸ãe“ha˜v˜e“to“insert“a“spGecial“line“for“ev˜ery“terminalŽ¡‘'¿¬tok¸ãen–ó§that“appGears“in“the“grammar“rules.‘Q8These“de nitions“are“of“the“form“`È%tokenŽ¡‘'¿¬ÎtokennameŽ‘WD7²'.‘óThis–€rpart“of“the“formatted“grammar“ le“is“o•¸ãw“ed–€rto“Bison“and“shouldŽ¡‘'¿¬bGe›UUremo•¸ãv“ed˜in˜subsequen“t˜v“ersions.ŽŽŽŒ‹86 ½\È ýN£8‘63ײ56’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜G ý„‘63×Í7.2.3Ž‘_s×Commen ts–€and“Co`deŽ©­m‘63ײThere–Ôis“a“vš¸ãery“simple“w˜a˜y“of“putting“commen˜ts“in˜to“the“formatted“tok˜en“andޤ ‘63×formatted–r grammar“ les.‘ÇâThis“is“done“in“a“ÇCŸÿ²++Ž‘Ekind“of“manner“b¸ãy“preceding“theŽ¡‘63×commenš¸ãt– ƒwith“a“double“slash“(`È//²').‘SQAll“c˜haracters“bGet˜w˜een“this“sign“and“the“endŽ¡‘63×of–UUthe“line“are“ignored“b¸ãy“pretzel.ŽŸ $‘E3×In–à bšGoth“ les“y¸ãou“can“put“additional“ÇCŸÿ²++Ž‘nGco˜de“b˜efore“and“after“the“de ni-Ž¡‘63×tions/grammar–kçsections.‘µ}If“yš¸ãou“w˜an˜t“to“insert“coGde“at“the“end“of“y˜our“ le,‘±‹y˜ouŽ¡‘63×ha•¸ãv“e–¶Ýto“put“a“second“`È%%²'“on“a“line“b¸ãy“itself“and“put“the“cošGde“b˜ehind“it.‘–^ÇC²/ÇCŸÿ²++ŽŽ¡‘63×Co•Gde›Õßb“efore˜the˜de nitions/rules˜section˜has˜to˜b“e˜tied˜in˜with˜a˜`%¸f²',‘ö`%¸g²'˜pair.Ž¡‘63×Inserting–í€extra“cošGde“is“in¸ãteresting“for“p˜eople“who“w•¸ãan“t–í€to“call“this“co˜de“from“withinŽ¡‘63×the–UUattribute“de nitions.‘qÇSee“section“3.1“for“details.ŽŸ!±°‘63×Ì7.3Ž‘[:Synopsis–ffof“Øpretzel“Ìand“Øpretzel-itŽŸ4‘63×Í7.3.1Ž‘_s×Üpretzel-itަ‘63ײThe–¹Fshell“script“Èpretzel-it“²uses“Pretzel“to“build“a“simple“prett•¸ãyprin“ter‘¹Fexecutable.Ž¡‘63×It–UUminimizes“building“a“Pretzel“prett•¸ãyprin“ter–UUto“just“one“shell“command.Ž© $‘E3×Y‘ÿ*ªou›ò§ha•¸ãv“e˜to˜pro“vide˜the˜same˜t“w“o˜input˜ les˜to˜Èpretzel-it˜²as˜to˜Pretzel.Ž¡‘63×These›úÙt•¸ãw“o˜ les˜are˜called˜the˜formatted˜tok“en˜ le˜(sux˜È.ft²)˜and˜the˜formattedŽ¡‘63×grammar–ûF le“(sux“È.fg²).›SÂBoth“ les“need“to“ha•¸ãv“e–ûFthe“same“pre x.˜F‘ÿ*ªrom“this“input,Ž¡‘63×Èpretzel-it–UU²generates“an“executable“prett•¸ãyprin“ter.ަ‘E3×T‘ÿ*ªo–UUget“to“knoš¸ãw“the“options,“t˜ypGeޤZm‘@³ÑÈpretzel-it‘?ý-hŽ¡‘63ײat–UUthe“command“line.‘qÇThe“full“usage“is:Ž¡‘@³ÑÈpretzel-it–?ý[-iqvdnh]“language“ppnameŽ¡‘63ײHere's–UUan“explanation“of“the“options:Ž¡‘63ׯ-iŽŽ‘B:ñ²Don't›UUremo•¸ãv“e˜in“termediate˜proGducts˜of˜pretzeling.ޤx’‘63ׯ-qŽŽ‘Eð²Run‘UUquietly‘ÿ*ª.Ž¡‘63ׯ-vŽŽ‘Eð²V‘ÿ*ªerb•Gose›UUmo“de,˜prin¸ãt˜shell˜commands˜b“efore˜in•¸ãv“oking˜(for˜debugging).Ž¡‘63ׯ-dŽŽ‘El·²T‘ÿ*ªurn›H;prett•¸ãyprin“ter˜debugging˜features˜on˜b“y˜default˜(for˜debugging˜the˜pret-Ž© ‘O3Ùt•¸ãyprin“ting‘UUgrammar).Ž¡‘63ׯ-hŽŽ‘El·²Prin¸ãt–UUfull“usage“message.Ž¡‘63ׯ-nŽŽ‘El·²No•¸ãw“eb–ø(mošGde,‘ Êwill“pro˜duce“a“prett•¸ãyprin“ting–ø( lter“Èppname“²compatible“to“Normanަ‘O3ÙRamsey's–Ènoweb“²literate“programming“system.‘^_The“ lter“can“bGe“inserted“in¸ãtoަ‘O3Ùthe–UUÈnoweb“²pipGeline“using“Ènoweave²'s“È-filter“²option.ޤZm‘63×See–UUalso“the“manpage“Èpretzel-it“²and“c¸ãhapters“2“and“4.ŽŸž"‘63×Í7.3.2Ž‘_s×ÜpretzelŽŸ­m‘63ײPretzel–UUis“in•¸ãv“ok“ed›UUb“y˜t“ypingŽ¡‘@³ÑÈpretzelŽ¡‘63ײat–žthe“command“line.‘AêThe“full“usage“of“Pretzel“can“bGe“obtained“using“the“È-h“²option.ަ‘63×It‘UUis:ŽŽŽŒ‹9' ½\È ýN£8‘'¿¬Ã7.3.‘ÇSYNOPSIS–UUOF“ÈPRETZEL“ÃAND“ÈPRETZEL-IT’Рײ57ŽŽ ˜G ý„‘2?¦Èpretzel–?ý[-qtgdh]“[-o“outfile]“(prefix“|“file1“file2)ޤ‘'¿¬²Here's–UUan“explanation“of“the“options:Ž¡‘'¿¬Æ-qŽŽ‘6¦Å²Run–UUquietly“(no“screen“output).Ž¡‘'¿¬Æ-tŽŽ‘5 â²ProGcess–UUformatted“tok¸ãen“ le“only‘ÿ*ª.Ž¡‘'¿¬Æ-gŽŽ‘6Tþ²ProGcess–UUformatted“grammar“ le“only‘ÿ*ª.Ž¡‘'¿¬Æ-dŽŽ‘6øŒ²Run–ûšin“debug“moGde“(i.e.“prin¸ãt“out“debugging“information“on“the“screen“whileŽ© ‘@¿®running).Ž¡‘'¿¬Æ-hŽŽ‘6øŒ²Sho¸ãw–UUfull“usage.Ž¡‘'¿¬Æ-o‘ÕTout leŽŽ‘Y¡d²Names–UUof“the“prošGduced“output“ les“b˜egin“with“\out le".Ž¡‘'¿¬The–G§options“È-t“²and“È-g“²are“mš¸ãutually“exclusiv˜e,‘„;i.e.“y˜ou“can't“c˜hošGose“b˜oth“at“theަ‘'¿¬same‘UUtime.ަ‘6¿¬The–žcommand“line“parameters“ha•¸ãv“e›ždi eren“t˜meanings˜depGending˜on˜whetherަ‘'¿¬one–€rore“t•¸ãw“o–€rnames“are“giv¸ãen.‘óIf“there“is“only“one“parameter,‘‹9it“spGeci es“the“pre xަ‘'¿¬of–EcbGoth“formatted“tok¸ãen“and“formatted“grammar“ les.‘lvThe“suxes“`È.ft²'“and“`È.fg²'ަ‘'¿¬are–%“assumed.‘â€But“if“there“are“t•¸ãw“o–%“parameters“at“the“command“line,‘Y¢Pretzel“willަ‘'¿¬takš¸ãe–ô‡the“ rst“as“full“name“of“the“formatted“tok˜en“ le“and“the“second“as“full“name“ofަ‘'¿¬the–¨Kformatted“grammar“ le.‘j¨In“this“case,‘½the“output“ les“will“get“a“default“name.ަ‘'¿¬The–UUoutput“ les“will“ha•¸ãv“e–UUendings“`È.l²'“(tok¸ãen“ le)“and“`È.y²'“(grammar“ le).ŽŽŽŒ‹: Ë ½\È ýN£8‘63ײ58’ÚÙ‰ÃCHAPTER‘UU7.‘ÇREFERENCEŽŽ ˜GŽŒ‹;&® ½\È ýN£8 ˜G ýÔ,‘'¿¬ÅBibliograph‘ÿ8õyŽŸ5‚~‘,¿­²[1]ŽŽ‘ÃURL:Ž¡‘@¼ ½\È ýN£8‘63ײ62’kSÃBIBLIOGRAPHYŽŽ ˜G ý„‘63ײ[56]ŽŽ‘JÂLisa–«ÙF.“Rubin.‘ZªSynš¸ãtax-directed“prett˜y“prin˜ting“|“a“ rst“step“to˜w˜ards“a“syn˜tax-ޤ ‘JÂdirected‘­editor.‘]uÎIEEE‘ùgT‘ÿ;¼r›ÿ}'ansactions–ùon“Softwar˜e“Engine˜ering²,‘ÏSE-9(2):119{127,Ž¡‘JÂMarc¸ãh‘UU1983.Ž©‘63×[57]ŽŽ‘JÂJoac•¸ãhim›ž¦Sc“hroGd.‘:Latex˜cw“eb˜|˜a˜bundle˜that˜allo“ws˜y“ou˜to˜use˜la-Ž¡‘JÂtex–®ªas“the“doGcumenš¸ãtation“markup“of“y˜our“cw˜eb“program.‘ nëWWW‘®URL:Ž¡‘JÂÈftp://ftp.th-darmstadt.de/‘?ýpub/programming/literate-programming/Ž¡‘JÂc.c++/cweb-sty-1.1.1.tar.gz².ަ‘63×[58]ŽŽ‘JÂBarry› íSc•¸ãh“w“artz.‘ >When˜to˜use˜prett“yprin“ting.‘ >P“osting˜inŽ¡‘JÂÈcomp.programming.literate²,‘ ÚòOctobGer–1994.‘ûVCorrect“sub‘Ž8ject“headerŽ¡‘JÂmighš¸ãt–UUbGe“di eren˜t.“Date“here:‘qÇ5“Oct“1994.ަ‘63×[59]ŽŽ‘JÂR.›ÅçSco•¸ãw“en,–â—D.˜Allin,“A.˜L.˜Hillman,“and˜M.˜Shimell.‘…"SO¸ãAP–ÅÂ{˜A“program˜whic¸ãhŽ¡‘JÂdoGcumen¸ãts–†Ÿand“edits“Algol60“programs.‘ûÎThe–Õ¼Computer“Journal²,‘¯÷14(2):133{135,Ž¡‘JÂ1971.ަ‘63×[60]ŽŽ‘JÂMarc– v‘ÿqÇan“Leeu•¸ãw“en.›b When– to“use“prett•¸ãyprin“ting.˜P“osting‘ inŽ¡‘JÂÈcomp.programming.literate²,‘·žOctobGer–pÃ1994.‘»Correct“sub‘Ž8ject“header“migh¸ãtŽ¡‘JÂbGe–UUdi eren¸ãt.“Date“here:‘qÇ7“Oct“1994.ަ‘63×[61]ŽŽ‘JÂMarc–Tev‘ÿqÇan“Leeu•¸ãw“en.‘ÌDi erences›TebGet“w“een˜CWEB–T$and˜WEB“prett•¸ãyprin“ting˜gram-Ž¡‘JÂmars.›2sP¸ãosting––ñin“Ècomp.programming.literate²,‘§XF‘ÿ*ªebruary“1995.˜Correct“sub-Ž¡‘JÂject–UUheader“mighš¸ãt“bGe“di eren˜t.ަ‘63×[62]ŽŽ‘JÂMarc–¹v‘ÿqÇan“Leeu•¸ãw“en.‘ˆ¯On›¹in“terpretation˜of˜la“y“out˜features.‘ˆ¯P“osting˜inŽ¡‘JÂÈcomp.programming.literate²,–UUF‘ÿ*ªebruary“1995.‘nïCorrect“sub‘Ž8ject“wš¸ãas“di eren˜t.ަ‘63×[63]ŽŽ‘JÂMarc–„èv‘ÿqÇan“Leeu•¸ãw“en.› í^Alignmen“t–„èof“assignmen¸ãts“in“ÈCWEAVE².˜P¸ãosting“inŽ¡‘JÂÈcomp.programming.literate²,‘½^Marcš¸ãh–¨1996.‘fôCorrect“sub‘Ž8ject“header“migh˜t“bGeŽ¡‘JÂdi erenš¸ãt–UU(date“and“n˜um˜bGer“here:‘qÇ2986,“19“Mar“1996.ަ‘63×[64]ŽŽ‘JÂMarc–x-v‘ÿqÇan“Leeu•¸ãw“en.‘ѧPrett“yprin“ting–x-in“no•¸ãw“eb›x-(w“as:‘·vthe˜underscore˜dilema).Ž¡‘JÂP¸ãosting–UUin“Ècomp.programming.literate²,“April“1996.ަ‘63×[65]ŽŽ‘JÂR.–ìÌW‘ÿ*ªaters.‘2NUser“format“conš¸ãtrol“in“a“LISP‘ì¥prett˜yprin˜ter.‘2NÎA¾“CM‘T‘ÿ;¼r‘ÿ}'ansactionsŽ¡‘JÂon›“çPr–ÿ}'o“gr“amming˜L“anguages˜and˜Systems²,–UU5(4):513{531,“OctobGer“1983.ަ‘63×[66]ŽŽ‘JÂR.C.–mtW‘ÿ*ªaters.‘¶ÑUsing“the“new“common“LISP‘mnprettš¸ãy“prin˜ter.‘¶ÑÎLisp–ªand“Symb‘ÿ}'olicŽ¡‘JÂComputation²,–UUV(2):27{34,“April{June“1992.ަ‘63×[67]ŽŽ‘JÂK.–ΉWinš¸ãter“and“C.“Co•Gok.‘“5A‘Îgprotot˜yp“e–Ήin˜telligen˜t“prett˜yprin˜ter“for“P˜ascal.‘“5ÎA¾“CMŽ¡‘JÂSIGPLAN‘“çNotic‘ÿ}'es²,–UU24(9):116{125,“Septem¸ãbGer“1989.ަ‘63×[68]ŽŽ‘JÂM.‘ƒrW›ÿ*ªo•Go“dman.‘ó=F˜ormatted–ƒrsyn¸ãtaxes“and“MoGdula-2.‘ó=ÎSoftwar›ÿ}'e–©Ù|“Pr˜actic˜e“&Ž¡‘JÂExp–ÿ}'erienc“e²,–UU16(7):605{626,“July“1986.ަ‘63×[69]ŽŽ‘JÂA.–5ýY‘ÿ*ªehš¸ãudai.‘ jAutomatic“inden˜tation“v˜ersus“program“formatting.‘ jÎA¾“CM‘baSIG-Ž¡‘JÂPLAN‘“çNotic‘ÿ}'es²,–UU15(10):85{87,“1980.ŽŽŽŒ‹?N ½\È ýN£8 ˜G ýÑGŸì‘'¿¬ÅIndexŽŽ .¸å ýïG‘'¿¬È/*².–ªª.“.“È*/–UU²commen¸ãts,“49ޤ é‘'¿¬È//–UU²commen¸ãts,“49Ž¡‘'¿¬[,–UUcoGde“delimiters,“23Ž¡‘'¿¬2.0,‘UU6Ž©N‘'¿¬A¸ãCM,‘UU42Ž¡‘'¿¬Ada,‘UU41Ž¡‘'¿¬\adaptiv•¸ãe›UUcom“bs",˜47Ž¡‘'¿¬adding–UUcoGde,“23Ž¡‘'¿¬Additional–UUspacing,“43Ž¡‘'¿¬AIX,‘UU6Ž¡‘'¿¬ÇAlgol²,–UU41,“42Ž¡‘'¿¬Algorithm-pGolicy–UUdistinction,“43Ž¡‘'¿¬ASCIGI,‘UU33Ž¡‘'¿¬Assem•¸ãbler›UUlik“e˜command˜set,˜46Ž¡‘'¿¬attac•¸ãhmen“ts,‘UU13Ž¡‘'¿¬Èattr.nw²,‘UU23Ž¡‘'¿¬A¸ãttribute–UUclass,“23Ž¡‘'¿¬attribute–UUde nitions,“11Ž¡‘'¿¬attributes,‘UU13Ž¡‘'¿¬Automatic–UUt¸ãypGesetting,“41Ž¡‘'¿¬a¸ãv‘ÿqÇailable–UUgrammars,“19ަ‘'¿¬Bac¸ãk–UUend,“44Ž¡‘'¿¬bac¸ãkup,‘UU15Ž¡‘'¿¬Îb‘ÿ}'ackupŽ‘EAì²,–UU15,“47Ž¡‘'¿¬Basic–UUactions“of“prett•¸ãyprin“ters,‘UU43Ž¡‘'¿¬Beaut¸ãy‘ÿ*ª,‘UU42Ž¡‘'¿¬Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘Mɲ,–UU15,“46Ž¡‘'¿¬Bison,–UU6,“11,“18,“32,“52Ž¡‘'¿¬Blasc¸ãhek,–UUG.,“44,“48Ž¡‘'¿¬b•Go“oks,‘UU18Ž¡‘'¿¬breakspace,‘UU14Ž¡‘'¿¬Îbuild‘‰ffŽ‘®pp‘ÿ}'arseŽ‘\›ˆ²,‘UU50ަ‘'¿¬C,–UU17,“19Ž¡‘'¿¬ÇC²,–UU16,“47,“55Ž¡‘'¿¬C–UUcoGde“in“rules,“23Ž¡‘'¿¬ÇC–UU²preproGcessor,“16Ž¡‘'¿¬ÇCŸÿ²++Ž‘Ž<,–UU16,“47,“51,“56Ž¡‘'¿¬Îc–ÿ}'anc“elŽ‘BÙ8²,–UU16,“37,“47Ž¡‘'¿¬\case"–UUconstruct,“43Ž¡‘'¿¬c¸ãhristmas–UU1996,“6Ž¡‘'¿¬Classes–UUof“commen¸ãts,“48Ž¡‘'¿¬coGde–UUdelimiters,“23ŽŽŽ ýïG’íìzcoGde–UUin“attributesޤ ®’ìzsummary‘ÿ*ª,‘UU25Ž¡’íìzcolon,‘UU11Ž¡’íìzcom¸ãbining–UUrules,“11Ž¡’íìzCommand‘UUsetŽ¡’ìzassem•¸ãbler›UUlik“e,˜46Ž¡’ìzcon•¸ãv“enien“t,‘UU47Ž¡’ìzsuciency‘ÿ*ª,‘UU45Ž¡’ìzsucien¸ãt,‘UU47Ž¡’íìzCommen¸ãts,‘UU48Ž¡’ìzin–UUPretzel“input“ les,“56Ž¡’íìzComm¸ãunication–UUprotoGcol,“43Ž¡’íìzÈcomp.programming.literate²,‘UU6Ž¡’íìzCompilersŽ¡’ìzand›UUprett•¸ãyprin“ters,˜42Ž¡’ìzfor–UUdoGcumen¸ãts,“42Ž¡’íìzcompilers,‘UU18Ž¡’íìzcomplex–UUlanguages,“16Ž¡’íìzcomplex–UUtok¸ãens,“11Ž¡’íìzConnector–UUlines,“43Ž¡’íìzCon¸ãtext–UUfree“grammar,“46,“54Ž¡’íìzcon¸ãtext–UUfree“grammar,“11Ž¡’íìzcon¸ãtext–UUfree“grammars,“18Ž¡’íìzCon•¸ãtext›UUsensitiv“e˜formatting,˜48Ž¡’íìzcon•¸ãtext›UUsensitiv“e˜grammars,˜18,˜21Ž¡’íìzCon¸ãtrol–UUsequences,“42Ž¡’íìzcon¸ãtrol–UUsequences,“13Ž¡’íìzcon•¸ãtrolling›UUinden“tation,˜13Ž¡’íìzcon¸ãtrolling–UUline“breaks,“14Ž¡’íìzCon•¸ãv“enien“t–UUcommand“set,“47Ž¡’íìzCon•¸ãv“en“tions,‘UU52Ž¡’íìzCoGok,–UUC.,“48Ž¡’íìzCop•¸ãy›UUcommen“ts,˜49Ž¡’íìzCoroutines,‘UU43Ž¡’íìzcreate,‘UU24Ž¡’íìzCWEB,‘UU7Ž¡’íìzÈCWEB²,‘UU37ŽŸÎW’íìzÈ-d–UU²option“of“Bison,“30Ž¡’íìzÈ-d–UU²option“of“Èpretzel-it²,“20,“29Ž¡’íìzDarmstadt,‘UU6Ž¡’íìzdateŽ¡’ìzup–UUto,“6Ž¡’íìzdebug–UUo “function,“29Ž¡’íìzdebug–UUon“function,“29ŽŽŽŽŽŽŸK’×lx63ŽŽŒ‹@Z¨ ½\È ýN£8‘63ײ64’>KZÃINDEXŽŽ ˜G ý„‘63ײdebug–UUprin¸ãt,“26ޤ J‘63×debugging–UUgrammars,“19Ž¡‘63×debugging–UUmoGde,“20Ž¡‘63×De ating›8ãprett•¸ãyprin“ting˜grammars,‘qÇ47Ž¡‘63×È-delay–UU²switc¸ãh,“36Ž¡‘63×DoGcumen¸ãt–UUcompilers,“42Ž¡‘63×doGcumen•¸ãts,›UUo“wn,˜9Ž¡‘63×Dublin,‘UU6Ž¡‘63×Dv¸ãorak,–UUJan,“42Ž©Ù‘63×Early›UUprett•¸ãyprin“ters,˜43Ž¡‘63×EditorsŽ¡‘J3×syn¸ãtax–UUdirected,“44Ž¡‘63×Empt•¸ãy›UUtok“ens,˜49Ž¡‘63×ending–UUcoGde,“25Ž¡‘63×Equalit¸ãy‘ÿ*ª,‘UU48Ž¡‘63×error–UUtok¸ãen,“20Ž¡‘63×escapGed–UUunderlines,“24Ž¡‘63×ev•¸ãeryda“y–UUsetting,“7Ž¡‘63×Èexample-frame.tex²,‘UU9Ž¡‘63×Exceptions,‘UU16Ž¡‘63×executable›UUprett•¸ãyprin“ter,˜9Ž¡‘63×expGectations,‘UU9Ž¡‘63×Explicit–UUformat“commands,“44ަ‘63×È.fg–UU²sux,“52,“57Ž¡‘63×FIF¸ãO–UUbu er,“43Ž¡‘63×File–UUformats,“52Ž¡‘63×Filename›UUcon•¸ãv“en“tions,˜52Ž¡‘63×È-filter–UU²switc¸ãh,“36Ž¡‘63× ex,–UU6,“11,“32,“52Ž¡‘63× exdoGc,–UU11,“32Ž¡‘63×Flexibilit¸ãy‘ÿ*ª,‘UU16Ž¡‘63×F‘ÿ*ªolding,–UU43,“45Ž¡‘63×F›ÿ*ªolding–¾¼algorithm“(Rose“and“W˜elsh),ŽŸ ‘^3×44Ž¡‘63×force,‘UU13Ž¡‘63×Îfor–ÿ}'c“eŽ‘K†£²,‘UU37Ž¡‘63×formal–UUlanguage“theory‘ÿ*ª,“18Ž¡‘63×F‘ÿ*ªormal–UUmethoGds,“44Ž¡‘63×F‘ÿ*ªormat–UUcommands,“43Ž¡‘J3×Îb‘ÿ}'ackupŽ‘g¶²,–UU15,“47Ž¡‘J3×Îbig‘‰ffŽ‘®for–ÿ}'c“eŽ‘oxô²,–UU15,“46Ž¡‘J3×Îc–ÿ}'anc“elŽ‘eMc²,–UU16,“47Ž¡‘J3×explained,‘UU16Ž¡‘J3×explicit,‘UU44Ž¡‘J3×implicit,‘UU44Ž¡‘J3×Îno‘‰ffŽ‘®indentŽ‘t蜲,–UU16,“47Ž¡‘J3×Înul‘‚ØlŽ‘[ØÌ²,‘UU16Ž¡‘J3×summary‘ÿ*ª,‘UU16Ž¡‘63×format‘UUcommandsŽ¡‘J3×additional,‘UU15Ž¡‘J3×bac¸ãkup,‘UU15Ž¡‘J3×breakspace,‘UU14ŽŽŽ ý„’`¥extra,‘UU37ޤ ¬’`¥opt,‘UU15Ž¡’ü`¥F‘ÿ*ªormatted–UUgrammar“ le,“52,“54Ž¡’ü`¥formatted–UUgrammar“ le,“10,“11Ž¡’ü`¥F‘ÿ*ªormatted–UUtok¸ãen“ le,“52,“53Ž¡’ü`¥formatted–UUtok¸ãen“ le,“10Ž¡’`¥placemen¸ãt–ë[of“regular“expressions,ŽŸ ’$`¥11Ž¡’ü`¥formatting,‘UU13Ž¡’ü`¥F‘ÿ*ªormatting–UUalgorithm,“43Ž¡’ü`¥F‘ÿ*ªormatting–UUalgorithms,“41Ž¡’ü`¥formatting–UUinstructions,“12,“13Ž¡’ü`¥F–ÿ*ªormatting›UUpGolicy“,˜43,˜45Ž¡’ü`¥F‘ÿ*ªormatting–UUstandards,“41Ž¡’ü`¥\free–UUformat"“languages,“41Ž¡’ü`¥F‘ÿ*ªree›UUSoft•¸ãw“are˜F‘ÿ*ªoundation,˜6Ž¡’ü`¥F‘ÿ*ªron¸ãt–UUend,“44Ž¡’ü`¥È.ft–UU²sux,“52,“57Ž©å’ü`¥G‘úÿÿartner,–UUF‘ÿ*ªelix,“19Ž¡’ü`¥G‘úÿÿartner,–UUF‘ÿ*ªelix,“19Ž¡’ü`¥GNU–UUÈg++“²Compiler,“6Ž¡’ü`¥GNU–UUGeneral“Public“License,“6Ž¡’ü`¥go•Go“d–UUnews,“19Ž¡’ü`¥grammar–UUrules,“13Ž¡’ü`¥grammar,–UUcon¸ãtext“free,“11Ž¡’ü`¥grammarsŽ¡’`¥prett•¸ãyprin“ting,‘UU16Ž¡’ü`¥Grogono,–UUP‘ÿ*ª.,“48Ž¡’ü`¥Guidelines–UU(Rose“and“W‘ÿ*ªelsh),“44ަ’ü`¥handling–UUiden¸ãti ers,“10Ž¡’ü`¥Hearn,–UUA.“C.,“43,“44Ž¡’ü`¥History–UUof“prett•¸ãyprin“ting,‘UU42Ž¡’ü`¥Hmmm,‘UU18Ž¡’ü`¥homepageŽ¡’`¥Pretzel,–UU6,“17Ž¡’ü`¥Horizon¸ãtal–UUspacing,“48Ž¡’ü`¥HP-UX,‘UU6Ž¡’ü`¥HTML,‘UU32Ž¡’ü`¥h¸ãum,–UUrattle“and,“9ަ’ü`¥Implicit–UUformat“commands,“44Ž¡’ü`¥In-text–UUproGcedural“markup,“42Ž¡’ü`¥Include–UU les“for“grammars,“50Ž¡’ü`¥inden¸ãt,‘UU13Ž¡’ü`¥Inden¸ãtation,‘UU43Ž¡’ü`¥inden¸ãtation,‘UU13Ž¡’ü`¥Inden•¸ãting‘æFprograms,‘ ‚Îse‘ÿ}'e‘¦¡²Prett“yprin“t-ŽŸ ’$`¥ersŽ¡’ü`¥È-index–UU²switc¸ãh,“36Ž¡’ü`¥Indexing–UUwith“Ènoweb²,“36Ž¡’ü`¥indexing,–UUautomatic,“7Ž¡’ü`¥Inituitiv¸ãe–UUgrammar“format,“50ŽŽŽŽŽŽŒ‹AeÖ ½\È ýN£8‘'¿¬ÃINDEX’>KZ²65ŽŽ ˜G ý„‘'¿¬install,‘UU24ޤ ‘'¿¬installing–UUPretzel,“6Ž¡‘'¿¬In•¸ãtelligen“t›UUprett“yprin“ter,˜48Ž¡‘'¿¬ITI,‘UU6Ž©™š‘'¿¬Jac•¸ãk“el,–UUM.,“48Ž¡‘'¿¬Ja¸ãv‘ÿqÇa,–UU17,“19,“36Ž¡‘'¿¬join,‘UU24ަ‘'¿¬Kaelbling,–UUM.“J.,“48Ž¡‘'¿¬Kehr,–UURoger,“6Ž¡‘'¿¬Kellington,–UUMyrtle,“42Ž¡‘'¿¬Kien¸ãtzle,–UUTim,“7Ž¡‘'¿¬Kloso¸ãwski,–UUPrzemek,“37Ž¡‘'¿¬Kn¸ãuth,–UUDonald“E.,“35,“42{44,“46Ž¡‘;¿¬command–UUset“b¸ãy‘ÿ*ª,“42ަ‘'¿¬È.l–UU²sux,“57Ž¡‘'¿¬Language–UU(in)depGendence,“44Ž¡‘'¿¬language–UUde nition“grammars,“18Ž¡‘'¿¬Language–UUdepGendenš¸ãt“fron˜t“end,“44Ž¡‘'¿¬Language–-¨indepGendenš¸ãt“bac˜k“end,‘c½44,Ž¡‘O¿¬45Ž¡‘'¿¬Èlanguages/examples²,‘UU7Ž¡‘'¿¬LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX,–UU9,“32Ž¡‘'¿¬Latex–UUcw¸ãeb“output,“26Ž¡‘'¿¬Ledgard,–UUHenry“F.,“41Ž¡‘'¿¬v‘ÿqÇan‘\DLeeu•¸ãw“en,–^Marc,“5,“16,“20,“32,“42,Ž¡‘O¿¬47,‘UU49Ž¡‘'¿¬Levy‘ÿ*ª,–UUSilvio,“43Ž¡‘'¿¬Lexical–UUlev¸ãel,“46Ž¡‘'¿¬line–UUbreaks,“14Ž¡‘'¿¬Link¸ãed–UUfolds,“48Ž¡‘'¿¬ÇLisp²,–UU41,“43Ž¡‘'¿¬literate–UUprogramming,“35Ž¡‘'¿¬loGokup–UUtable,“24ަ‘'¿¬Markup,–UU42,“46Ž¡‘'¿¬markup,‘UU13Ž¡‘'¿¬matc¸ãh–UUiput“patterns,“10Ž¡‘'¿¬Mateti,–UUP‘ÿ*ª.,“44Ž¡‘'¿¬McKeeman,–UUWilliam,“42Ž¡‘'¿¬Metasyn¸ãtax–UU(Rose“and“W‘ÿ*ªelsh),“44Ž¡‘'¿¬MoGdula-2,‘UU47Ž¡‘'¿¬MoGdularit¸ãy‘ÿ*ª,‘UU45Ž¡‘'¿¬moGdules,‘UU5Ž¡‘'¿¬Mohilner,–UUP¸ãatricia“R.,“48Ž¡‘'¿¬m¸ãuliple–UUmoGdules,“31ަ‘'¿¬È-n–UU²option“of“Èpretzel-it²,“36Ž¡‘'¿¬naming›UUcon•¸ãv“en“tions,˜38Ž¡‘'¿¬Naur,–UUP¸ãeter,“42Ž¡‘'¿¬Necessary–UUcommand“set,“46Ž¡‘'¿¬Neerac¸ãher,–UUMatthias,“38Ž¡‘'¿¬newlines,‘UU26ŽŽŽ ý„’íìznewsgroup,‘UU6ޤ $’íìz\No",‘UU45Ž¡’íìzÎno‘‰ffŽ‘®indentŽ’¡?²,–UU16,“47Ž¡’íìzNorman,–UUA.“C.,“43,“44Ž¡’íìzno•¸ãw“eb,–UU6,“35,“36Ž¡’ìzprett•¸ãyprin“ter–UUAPI,“36Ž¡’ìzproblems,‘UU39Ž¡’íìzno•¸ãw“eb.st“y‘ÿ*ª,‘UU39Ž¡’íìzÈnoweb.sty²,‘UU37Ž¡’íìzNro ,–UU13,“42Ž¡’íìzÎnul‘‚ØlŽ’ÿ‘o²,‘UU16Ž©Öƒ’íìzOmissions,‘UU49Ž¡’íìzOppGen,–UUDerek“C.,“44Ž¡’íìzopt,‘UU15Ž¡’íìzoutden¸ãt,‘UU13Ž¡’íìzo•¸ãwn›UUdoGcumen“ts,˜9ަ’íìzµP‘c²,‘UU51Ž¡’íìzP¸ãarse–UUtree,“44Ž¡’íìzparser–UUgenerator,“18Ž¡’íìzparsing,‘UU18Ž¡’íìzP¸ãascal,‘UU19Ž¡’íìzÇP‘ÿ ascal²,–UU18,“41{44,“49,“53,“55Ž¡’íìzP¸ãersonal–UUtaste,“41Ž¡’íìzPL/I,–UU41,“43Ž¡’íìzplacing–UUregular“expressions,“11Ž¡’íìzP¸ãolicy-algorithm–UUdistinction,“43Ž¡’íìzPOSIX,‘UU52Ž¡’íìz\pGostcommen¸ãts"–8ã(Rose“and“W‘ÿ*ªelsh),‘qÇ48Ž¡’íìzÈPparse–UU²class,“28Ž¡’íìzÈPPARSE‘¡E‰ff&fŽ‘Ç«NAME–UU²macro,“28,“31Ž¡’íìz\precommen¸ãts"–ü (Rose“and“W‘ÿ*ªelsh),‘ è48Ž¡’íìzPreproGcessing–8ãof“format“commands,‘qÇ16Ž¡’íìzPreproGcessor,‘UU16Ž¡’íìz\preproGcessor"–UUfor“prett•¸ãyprin“ting,‘UU44Ž¡’íìzPrettprin¸ãting–UUscanner,“52Ž¡’íìzprett•¸ãyprin“t–UUfunction,“28Ž¡’íìzPrett•¸ãyprin“terŽ¡’ìz rst,‘UU42Ž¡’ìzin•¸ãtelligen“t,‘UU48Ž¡’íìzprett•¸ãyprin“terŽ¡’ìzexecutable,‘UU9Ž¡’ìzgenerator,‘UU5Ž¡’íìzPrett•¸ãyprin“tersŽ¡’ìzbasic–UUactions,“43Ž¡’ìzearly–UUsystems,“43Ž¡’ìzfor–UUother“languages,“41Ž¡’ìzrunning–UUon“k•¸ãeyw“ords,‘UU43Ž¡’íìzPrett•¸ãyprin“ting,‘UU41Ž¡’ìzhistory‘ÿ*ª,‘UU42Ž¡’ìzlanguage–UU(in)depGendence,“44Ž¡’ìzproblems,‘UU47Ž¡’íìzprett•¸ãyprin“tingŽŽŽŽŽŽŒ‹BsR ½\È ýN£8‘63ײ66’>KZÃINDEXŽŽ ˜G ý„‘J3ײgrammars,‘UU16ޤ ‘‘J3×history‘ÿ*ª,‘UU12Ž¡‘J3×idea,‘UU13Ž¡‘J3×moGdules,‘UU5Ž¡‘J3×with–UUformat“commands,“13Ž¡‘63×Prett•¸ãyprin“ting‘UUgrammarŽ¡‘J3×include–UU les,“50Ž¡‘63×Prett•¸ãyprin“ting–UUgrammar,“16,“49,“50Ž¡‘J3×and–UUcommen¸ãts,“48Ž¡‘J3×de ating,‘UU47Ž¡‘63×prett•¸ãyprin“ting–UUgrammar,“11Ž¡‘J3×w•¸ãatc“hing–UUparse,“20Ž¡‘63×prett•¸ãyprin“ting–UUgrammars,“18Ž¡‘J3×a¸ãv‘ÿqÇailable,‘UU19Ž¡‘63×prett•¸ãyprin“ting–UUmoGdule,“30Ž¡‘63×Prett•¸ãyprin“ting–UUparser,“52Ž¡‘63×prett•¸ãyprin“ting–UUparser,“27Ž¡‘63×prett•¸ãyprin“ting–UUparser“in¸ãterface,“28Ž¡‘63×Prett•¸ãyprin“ting‘UUproblemsŽ¡‘J3×w¸ãorst–UUand“oldest,“48Ž¡‘63×prett•¸ãyprin“ting–UUscanner,“27Ž¡‘63×prett•¸ãyprin“ting–UUscanner“class,“27Ž¡‘63×PretzelŽ¡‘J3×currect–UUrelease,“6Ž¡‘J3×example–UUoutput,“9Ž¡‘J3× le–UUextensions,“7Ž¡‘J3×history‘ÿ*ª,‘UU6Ž¡‘J3×homepage,–UU6,“17Ž¡‘J3×input–UU les,“7,“10Ž¡‘J3×installing,‘UU6Ž¡‘J3×in¸ãterface,‘UU26Ž¡‘J3×output,‘UU9Ž¡‘J3×prett•¸ãyprin“ting–UUmethoGd,“10Ž¡‘63×Pretzel,‘UU49Ž¡‘J3×concept,‘UU51Ž¡‘J3×options,‘UU57Ž¡‘63×PretzelŽ¡‘J3×obtaining,‘UU6Ž¡‘J3×ultimate–UUsource,“5Ž¡‘63×ÈPRETZEL‘¡E‰ff&fŽ‘Ç«INCLUDE‘8›²en•¸ãvironmen“t‘8ãv‘ÿqÇariable,ŽŸ ‘^3×30Ž¡‘63×Èpretzel-it²,‘UU9Ž¡‘J3×option–UUÈ-d²,“20Ž¡‘63×Èpretzel-noweb.sty²,‘UU37Ž¡‘63×ProGcedural–UUmarkup,“42,“46Ž¡‘63×Program–UUformatting,“41Ž¡‘63×Pscan–UUclass,“27Ž¡‘63×ÈPscan.h–UU²header“ le,“27Ž¡‘63×ÈPSCAN‘¡E‰ff&fŽ‘Ç«NAME–UU²macro,“27,“30Ž¡‘63×Èptokdefs.h–UU²header“ le,“30ŽŸ…¬‘63×Ramsey‘ÿ*ª,–UUNorman,“6,“35,“36,“41Ž¡‘63×rattle–UUand“h¸ãum,“9Ž¡‘63×ÈREADME²,‘UU6ŽŽŽ ý„’ü`¥recursion,‘UU11ޤ J’ü`¥reducing–UUtok¸ãens,“11Ž¡’ü`¥reference–UUgrammars,“18Ž¡’ü`¥regular–UUexpressions,“10Ž¡’`¥placemenš¸ãt–8ãin“formatted“tok˜en“ le,ŽŸ ’$`¥11Ž¡’ü`¥restrictions,‘UU21Ž¡’ü`¥restrictions–UUof“Pretzel,“19Ž¡’ü`¥Reuseabilit¸ãy‘ÿ*ª,‘UU45Ž¡’ü`¥Rigid–UUformatting“rules,“44Ž¡’ü`¥robust–UUgrammars,“20Ž¡’ü`¥Rose,–UUG.“A.,“44{46,“48Ž¡’ü`¥RS6000,‘UU6Ž¡’ü`¥Rubin,–UULisa“F.,“43,“46Ž©Ù’ü`¥Sametinger,–UUJ.,“44Ž¡’ü`¥Sc•¸ãhroGd,›UUJoac“him,˜6Ž¡’ü`¥Sc•¸ãh“w“artz,–UUBarry‘ÿ*ª,“22,“39,“51Ž¡’ü`¥\scopGed–UUcommen¸ãts"“(Kaelbling),“48Ž¡’ü`¥scratc¸ãh,‘UU17Ž¡’ü`¥Second–UUclass“citizens,“48Ž¡’ü`¥semicolon,‘UU11Ž¡’ü`¥Separation–UUof“concerns,“44Ž¡’ü`¥setting,›UUev•¸ãeryda“y‘ÿ*ª,˜7Ž¡’ü`¥Èsimpas.ft²,‘UU7Ž¡’ü`¥Èsimpas.fg²,‘UU7Ž¡’ü`¥Èsimpaspp²,‘UU9Ž¡’ü`¥Èsmall-example.tex²,‘UU9Ž¡’ü`¥SpacingŽ¡’`¥additional,‘UU43Ž¡’`¥horizon¸ãtal,‘UU48Ž¡’`¥horzon¸ãtal,‘UU46Ž¡’`¥v¸ãertical,‘UU46Ž¡’ü`¥\spGecial–UUmark¸ãers",“43Ž¡’ü`¥SPIDER,‘UU18Ž¡’ü`¥standard–UUinput,“9Ž¡’ü`¥standard–UUoutput,“9Ž¡’ü`¥starting–UUcoGde,“25Ž¡’ü`¥State–UUof“the“art,“44Ž¡’ü`¥studen¸ãts,‘UU6Ž¡’ü`¥Suciency–UUof“command“set,“45Ž¡’ü`¥Sucien¸ãt–UUcommand“set,“47Ž¡’ü`¥Summary–UUof“format“commands,“16Ž¡’ü`¥sym¸ãbGolic–UUnames,“10Ž¡’ü`¥syn¸ãtax–UUerror,“20Ž¡’ü`¥Syn¸ãtax-directed–UUeditors,“44ަ’ü`¥T‘ÿ*ªags,‘UU42Ž¡’ü`¥tags,‘UU13Ž¡’ü`¥T‘ÿ*ªasteŽ¡’`¥pGersonal,‘UU41Ž¡’ü`¥T‘þU>Ÿ'EŽ‘ãxX,–UU13,“41,“42,“45Ž¡’ü`¥text–UUformatter,“13Ž¡’ü`¥tips–UUand“tric¸ãks,“26ŽŽŽŽŽŽŒ‹C€• ½\È ýN£8‘'¿¬ÃINDEX’>KZ²67ŽŽ ˜G ý„‘'¿¬È%token–UU²declarations,“11ޤ ‘'¿¬È%token–UU²de nitions,“49Ž¡‘'¿¬tok¸ãen–UUheader“ le,“30Ž¡‘'¿¬tok¸ãens,–UU10,“11Ž¡‘;¿¬sym¸ãbGolic–UUnames,“10Ž¡‘'¿¬T‘ÿ*ªoGoth,‘UU48Ž¡‘'¿¬T‘ÿ*ªradition,‘UU42Ž¡‘'¿¬T‘ÿ*ªric¸ãky–UUdetails,“16Ž¡‘'¿¬T‘ÿ*ªrinit¸ãy–UUCollege,“Dublin,“6Ž¡‘'¿¬T‘ÿ*ªro ,–UU13,“42Ž¡‘'¿¬T¸ãypGesetters,‘UU41Ž¡‘'¿¬T¸ãypGesetting–UUsystems,“41Ž¡‘'¿¬T•¸ãypGesetting›UUcommen“ts,˜48Ž©‘'¿¬Uhr,–UUHolger,“6,“19Ž¡‘'¿¬ultimate–UUsource,“5Ž¡‘'¿¬UNIX,–UU6,“13,“18Ž¡‘'¿¬ÇUNIX²,‘UU42Ž¡‘'¿¬USENET,‘UU6Ž¡‘'¿¬User–UUcon¸ãtrol,“47Ž¡‘'¿¬user‘UUcon¸ãtrolŽ¡‘;¿¬full,‘UU5Ž¡‘'¿¬using–UUPretzel“output,“9ަ‘'¿¬v¸ãertical–UUline,“11ަ‘'¿¬W‘ÿ*ªaldsc•¸ãhmidt,›UUHelm“ut,˜6Ž¡‘'¿¬w•¸ãatc“hing–UUthe“parse,“20Ž¡‘'¿¬ÈWEAVE²,‘UU42Ž¡‘'¿¬WEB,‘UU18Ž¡‘'¿¬ÈWEB²,‘UU45Ž¡‘'¿¬W‘ÿ*ªelsh,–UUJ.,“44{46,“48Ž¡‘'¿¬Win¸ãter,–UUK.,“48Ž¡‘'¿¬Witten¸ãbGerg,–UULee,“6,“19,“36Ž¡‘'¿¬W‘ÿ*ªo•Go“dman,–UUM.,“44,“47Ž¡‘'¿¬writing–UUgrammars,“17ަ‘'¿¬È.y–UU²sux,“57Ž¡‘'¿¬Y‘ÿ*ªeh¸ãudai,–UUA.,“47Ž¡‘'¿¬yytext,‘UU24ŽŽŽŽŽŽŒøÃƒ’À;è½\ÈŸp Có1߆µT cmtt12ó0߆µTáH cmtt12ó/¡8)Ïcmsl8ó.Œ-ø cmcsc10ó-߆µTff cmtt12ó*Œ-øff cmcsc10ó)#Ñfcmti8ó%Œ-ø cmcsc10ó$ßCÊscmtt8ó#ý': cmti10ó"ÂÖN  cmbx12ó!ÂÖN ff cmbx12óÂÖN ½q cmbx12óßê cmmi10óKñ`y cmr10óÙ“ Rcmr7ó†›Zcmr5óäO£ linew10óäO£ line10ù’Pßßßßßßpretzel-2.0n-2/doc/figures/0000755000000000000000000000000006135737701014275 5ustar rootrootpretzel-2.0n-2/doc/figures/detailed-concept.latex0000644000000000000000000000625405723320721020537 0ustar rootroot\setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(210,229)(0,588) \thinlines \put(180,750){\vector( 0,-1){ 36}} \put(180,702){\vector( 0,-1){ 27}} \put(180,642){\vector( 0,-1){ 45}} \put(180,798){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}grammar file}}} \put(180,756){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}Bison source}}} \put(180,705){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}C++ code}}} \put(180,663){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}prettyprinting}}} \put(177,588){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}prettyprinter}}} \put(186,780){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}pretzel}}} \put(186,729){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}Bison}}} \put(186,684){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}CC}}} \put(180,810){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}formatted}}} \put(180,651){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}parser}}} \put(105,717){\makebox(0,0)[b]{\smash{\SetFigFont{7}{8.4}{}common}}} \put(105,708){\makebox(0,0)[b]{\smash{\SetFigFont{7}{8.4}{}token header}}} \put(180,795){\vector( 0,-1){ 27}} \put( 30,795){\vector( 0,-1){ 30}} \put( 30,651){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}scanner}}} \put( 30,750){\vector( 0,-1){ 36}} \put( 30,699){\vector( 0,-1){ 27}} \put( 30,648){\line( 0,-1){ 30}} \put( 30,618){\vector( 1, 0){141}} \multiput(174,741)(-8.62500,0.00000){9}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput(105,741)(0.00000,-7.50000){3}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput(105,702)(0.00000,-6.00000){2}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \put( 36,696){\vector(-1, 0){0}} \multiput(105,696)(-8.62500,0.00000){8}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \put( 30,798){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}token file}}} \put( 30,756){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}flex source}}} \put( 30,705){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}C++ code}}} \put( 30,663){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}prettyprinting}}} \put( 33,780){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}pretzel}}} \put( 33,729){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}flex}}} \put( 36,684){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{it}CC}}} \put( 75,621){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{}is called by}}} \put( 30,810){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{}formatted}}} \end{picture} pretzel-2.0n-2/doc/figures/pretzel-in-concept.latex0000644000000000000000000000577605723325504021071 0ustar rootroot\setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(402,270)(6,561) \thinlines \put(264,783){\vector(-1, 0){ 60}} \put(204,591){\vector( 1, 0){ 60}} \put(108,759){\line( 0,-1){ 12}} \put(108,735){\vector( 0,-1){ 12}} \put(108,651){\line( 0,-1){ 12}} \put(108,627){\vector( 0,-1){ 15}} \multiput( 6,561)(8.87500,0.00000){25}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 6,819)(8.87500,0.00000){25}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 6,561)(0.00000,8.89655){30}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput(219,561)(0.00000,8.89655){30}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \put( 18,762){\framebox(180,42){}} \put( 18,657){\framebox(180,60){}} \put( 18,576){\framebox(180,33){}} \put(270,780){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}unformatted source code}}} \put(270,588){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}typeset document}}} \multiput( 6,687)(7.96040,0.00000){51}{\line( 1, 0){ 3.980}} \put(108,738){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}complex attribute}}} \put( 6,822){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinter}}} \put(108,630){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}text with markup}}} \put(108,780){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}prettyprinting scanner}}} \put(108,768){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}prettyprinting parser}}} \put( 42,792){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}flex/Bison generated functions:}}} \put(108,675){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}preprocessing of format commands}}} \put(108,693){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}attribute traversal}}} \put(108,663){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}transformation into strings}}} \put( 42,705){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}output object:}}} \put(108,582){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}formatting algorithm}}} \put( 42,597){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}document formatter (TeX):}}} \put(402,675){\makebox(0,0)[rb]{\smash{\SetFigFont{10}{12.0}{rm}language independent back end}}} \put(402,693){\makebox(0,0)[rb]{\smash{\SetFigFont{10}{12.0}{rm}language dependent front end}}} \end{picture} pretzel-2.0n-2/doc/figures/module-depends.latex0000644000000000000000000000671205723324461020244 0ustar rootroot\setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(300,327)(27,504) \put( 54,645){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}.ft}}} \put( 75,645){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}files}}} \put( 51,666){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}ftscan.h}}} \put( 33,606){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}ftparse.h}}} \put( 36,594){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}generator for the}}} \put( 36,585){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinting scanner}}} \put(207,585){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinting parser}}} \put(207,594){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}generator for the}}} \put(204,606){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}fgparse.h}}} \put(222,645){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}.fg}}} \put(243,645){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}files}}} \put(219,666){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}fgscan.h}}} \put(222,654){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}scanner for}}} \thinlines \put(213,573){\vector( 0,-1){ 33}} \put(213,636){\vector( 0,-1){ 12}} \put(195,639){\framebox(132,39){}} \put(195,579){\framebox(132,39){}} \put( 54,654){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}scanner for}}} \put(132,504){\framebox(93,33){}} \put( 36,819){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}run time library:}}} \put(153,519){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}pretzel.w}}} \put(102,765){\framebox(156,39){}} \put(102,702){\framebox(156,39){}} \put(177,762){\vector( 0,-1){ 15}} \put(108,732){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}attr.h}}} \put(111,720){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Attribute class}}} \put(108,795){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}output.h}}} \put(111,771){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Output class}}} \put(111,783){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}format command definitions}}} \put(111,708){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}functions \id{create()} and \id{join()}}}} \put( 27,636){\framebox(135,42){}} \put( 27,579){\framebox(135,39){}} \put(144,636){\vector( 0,-1){ 12}} \put(144,573){\vector( 0,-1){ 33}} \multiput( 27,690)(9.09091,0.00000){34}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 27,831)(9.09091,0.00000){34}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 27,690)(0.00000,8.81250){17}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput(327,690)(0.00000,8.81250){17}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \put(144,696){\vector( 0,-1){ 15}} \put(213,696){\vector( 0,-1){ 15}} \end{picture} pretzel-2.0n-2/doc/figures/concept.fig0000644000000000000000000000126505653232015016413 0ustar rootroot#FIG 2.1 80 2 6 65 38 110 56 2 2 0 1 -1 0 0 0 0.000 0 0 0 110 56 110 38 65 38 65 56 110 56 9999 9999 4 1 0 10 0 -1 0 0.00000 2 9 30 89 50 pretzel -6 2 2 0 1 -1 0 0 0 0.000 0 0 0 125 95 125 77 53 77 53 95 125 95 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 86 62 86 71 9999 9999 2 1 0 3 -1 0 0 0 0.000 -1 0 0 29 86 47 86 9999 9999 2 1 0 3 -1 0 0 0 0.000 -1 0 0 128 86 152 86 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 86 20 86 32 9999 9999 4 1 0 10 0 -1 0 0.00000 2 9 55 89 89 prettyprinter 4 1 0 10 0 -1 0 0.00000 2 7 20 17 89 Text 4 1 0 10 0 -1 0 0.00000 2 9 56 182 80 prettyprinted 4 1 0 10 0 -1 0 0.00000 2 6 18 176 95 text 4 1 0 10 0 -1 0 0.00000 2 9 77 89 17 formal description pretzel-2.0n-2/doc/figures/generator-funs.fig0000644000000000000000000000174505723323344017726 0ustar rootroot#FIG 2.1 80 2 6 41 20 77 29 4 0 5 10 0 -1 0 0.00000 2 7 18 41 29 .ft 4 0 1 10 0 -1 0 0.00000 2 7 15 62 29 file -6 6 11 125 107 146 4 1 1 10 0 -1 0 0.00000 2 9 92 59 146 prettyprinting scanner 4 1 1 10 0 -1 0 0.00000 2 7 61 59 134 flex source for -6 6 164 125 254 146 4 1 1 10 0 -1 0 0.00000 2 9 87 209 146 prettyprinting parser 4 1 1 10 0 -1 0 0.00000 2 7 66 209 134 Bison source for -6 6 194 20 230 29 4 0 5 10 0 -1 0 0.00000 2 9 18 194 29 .fg 4 0 1 10 0 -1 0 0.00000 2 7 15 215 29 file -6 2 1 0 1 -1 0 0 0 0.000 -1 0 0 59 35 59 74 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 59 89 59 125 9999 9999 2 2 0 1 -1 0 0 0 0.000 0 0 0 272 98 272 62 14 62 14 98 272 98 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 212 35 212 74 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 212 89 212 125 9999 9999 4 0 1 10 0 -1 0 0.00000 2 9 30 14 59 pretzel 4 1 3 10 0 -1 0 0.00000 2 10 62 59 86 build\_pscan() 4 1 3 10 0 -1 0 0.00000 2 10 66 212 86 build\_pparse() pretzel-2.0n-2/doc/figures/generator-funs.latex0000644000000000000000000000363105723323355020274 0ustar rootroot\setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(259,126)(14,693) \put( 63,810){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}file}}} \put( 60,693){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinting scanner}}} \put( 60,705){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}flex source for}}} \put(210,693){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinting parser}}} \put(210,705){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}Bison source for}}} \put(195,810){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}.fg}}} \put(216,810){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}file}}} \put( 42,810){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{tt}.ft}}} \thinlines \put( 60,804){\line( 0,-1){ 39}} \put(213,753){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}build\_pparse()}}} \put( 60,750){\vector( 0,-1){ 36}} \put( 15,741){\framebox(258,36){}} \put(213,804){\line( 0,-1){ 39}} \put(213,750){\vector( 0,-1){ 36}} \put( 15,780){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}pretzel}}} \put( 60,753){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}build\_pscan()}}} \end{picture} pretzel-2.0n-2/doc/figures/pp-concept.latex0000644000000000000000000000464605723320360017405 0ustar rootroot\setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(321,168)(9,666) \put( 93,738){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}and format commands}}} \thinlines \put(204,798){\vector(-1, 0){ 39}} \put(168,699){\vector( 1, 0){ 36}} \multiput( 9,741)(8.57143,0.00000){4}{\line( 1, 0){ 4.286}} \multiput(147,741)(8.13333,0.00000){23}{\line( 1, 0){ 4.067}} \put( 93,774){\line( 0,-1){ 18}} \put( 93,735){\vector( 0,-1){ 21}} \put( 24,681){\framebox(138,33){}} \put( 93,747){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{it}stream of strings}}} \put( 24,777){\framebox(138,33){}} \put( 93,693){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}formatting algorithm}}} \multiput( 15,666)(6.00000,0.00000){27}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 15,822)(6.00000,0.00000){27}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput( 15,666)(0.00000,6.00000){27}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \multiput(171,666)(0.00000,6.00000){27}{\makebox(0.1111,0.7778){\SetFigFont{5}{6}{rm}.}} \put(210,696){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}typeset document}}} \put(210,795){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}unformatted source code}}} \put( 24,825){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinter}}} \put(330,747){\makebox(0,0)[rb]{\smash{\SetFigFont{10}{12.0}{rm}language dependent front end}}} \put(330,729){\makebox(0,0)[rb]{\smash{\SetFigFont{10}{12.0}{rm}language independent back end}}} \put( 93,798){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}parser using}}} \put( 93,786){\makebox(0,0)[b]{\smash{\SetFigFont{10}{12.0}{rm}prettyprinting grammar}}} \end{picture} pretzel-2.0n-2/doc/figures/pp-concept.fig0000644000000000000000000000240505723320352017025 0ustar rootroot#FIG 2.1 80 2 6 59 80 128 92 4 1 3 10 0 -1 0 0.00000 2 10 67 92 92 stream of strings -6 6 47 89 137 101 4 1 3 10 0 -1 0 0.00000 2 10 89 92 101 and format commands -6 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 203 41 164 41 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 1 0 0 1.000 4.000 8.000 203 140 167 140 9999 9999 2 1 1 1 -1 0 0 0 4.000 -1 0 0 8 98 38 98 9999 9999 2 1 1 1 -1 0 0 0 4.000 -1 0 0 146 98 329 98 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 92 65 92 83 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 92 104 92 125 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 161 158 161 125 23 125 23 158 161 158 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 161 62 161 29 23 29 23 62 161 62 9999 9999 2 2 2 1 -1 0 0 0 2.000 0 0 0 170 173 170 17 14 17 14 173 170 173 9999 9999 4 0 1 10 0 -1 0 0.00000 2 9 72 209 143 typeset document 4 0 1 10 0 -1 0 0.00000 2 7 100 209 44 unformatted source code 4 0 1 10 0 -1 0 0.00000 2 9 55 23 14 prettyprinter 4 2 1 10 0 -1 0 0.00000 2 9 119 329 92 language dependent front end 4 2 1 10 0 -1 0 0.00000 2 9 123 329 110 language independent back end 4 1 1 10 0 -1 0 0.00000 2 9 49 92 41 parser using 4 1 1 10 0 -1 0 0.00000 2 9 99 92 53 prettyprinting grammar 4 1 1 10 0 -1 0 0.00000 2 9 90 92 146 formatting algorithm pretzel-2.0n-2/doc/figures/module-depends.fig0000644000000000000000000000500705723324451017667 0ustar rootroot#FIG 2.1 80 2 6 50 164 98 194 4 0 1 10 0 -1 0 0.00000 2 7 45 53 185 scanner for 4 0 5 10 0 -1 0 0.00000 2 7 18 53 194 .ft 4 0 1 10 0 -1 0 0.00000 2 7 19 74 194 files 4 0 5 10 0 -1 0 0.00000 2 7 48 50 173 ftscan.h -6 6 32 224 128 254 4 0 5 10 0 -1 0 0.00000 2 9 54 32 233 ftparse.h 4 0 1 10 0 -1 0 0.00000 2 9 69 35 245 generator for the 4 0 1 10 0 -1 0 0.00000 2 9 92 35 254 prettyprinting scanner -6 6 194 161 326 299 6 203 224 293 254 4 0 1 10 0 -1 0 0.00000 2 9 87 206 254 prettyprinting parser 4 0 1 10 0 -1 0 0.00000 2 9 69 206 245 generator for the 4 0 5 10 0 -1 0 0.00000 2 9 54 203 233 fgparse.h -6 6 218 164 266 194 6 218 164 266 194 4 0 5 10 0 -1 0 0.00000 2 9 18 221 194 .fg 4 0 1 10 0 -1 0 0.00000 2 7 19 242 194 files 4 0 5 10 0 -1 0 0.00000 2 9 48 218 173 fgscan.h -6 6 221 176 266 185 4 0 1 10 0 -1 0 0.00000 2 7 45 221 185 scanner for -6 -6 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 212 266 212 299 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 212 203 212 215 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 326 200 326 161 194 161 194 200 326 200 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 326 260 326 221 194 221 194 260 326 260 9999 9999 -6 6 131 302 224 335 2 4 0 1 -1 0 0 0 0.000 7 0 0 224 335 224 302 131 302 131 335 224 335 9999 9999 4 0 5 10 0 -1 0 0.00000 2 9 54 152 320 pretzel.w -6 6 101 35 263 137 2 4 0 1 -1 0 0 0 0.000 7 0 0 257 35 257 74 101 74 101 35 257 35 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 257 98 257 137 101 137 101 98 257 98 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 176 77 176 92 9999 9999 4 0 5 10 0 -1 0 0.00000 2 7 36 107 107 attr.h 4 0 1 10 0 -1 0 0.00000 2 7 63 110 119 Attribute class 4 0 5 10 0 -1 0 0.00000 2 9 48 107 44 output.h 4 0 1 10 0 -1 0 0.00000 2 9 52 110 68 Output class 4 0 1 10 0 -1 0 0.00000 2 7 117 110 56 format command definitions 4 0 1 10 0 -1 0 0.00000 2 9 153 110 131 functions \id{create()} and \id{join()} -6 2 4 0 1 -1 0 0 0 0.000 7 0 0 161 203 161 161 26 161 26 203 161 203 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 161 260 161 221 26 221 26 260 161 260 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 143 203 143 215 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 143 266 143 299 9999 9999 2 2 2 1 -1 0 0 0 3.000 7 0 0 326 149 326 8 26 8 26 149 326 149 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 143 143 143 158 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 212 143 212 158 9999 9999 4 0 1 10 0 -1 0 0.00000 2 9 69 35 20 run time library: pretzel-2.0n-2/doc/figures/pretzel-in-concept.fig0000644000000000000000000000344005723325476020513 0ustar rootroot#FIG 2.1 80 2 2 1 1 1 -1 0 0 0 4.000 -1 0 0 5 152 407 152 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 263 56 203 56 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 203 248 263 248 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 107 80 107 92 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 107 104 107 116 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 0 0 107 188 107 200 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 107 212 107 227 9999 9999 2 2 2 1 -1 0 0 0 3.000 0 0 0 218 278 218 20 5 20 5 278 218 278 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 197 77 197 35 17 35 17 77 197 77 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 197 182 197 122 17 122 17 182 197 182 9999 9999 2 4 0 1 -1 0 0 0 0.000 7 0 0 197 263 197 230 17 230 17 263 197 263 9999 9999 4 0 1 10 0 -1 0 0.00000 2 7 100 269 59 unformatted source code 4 0 1 10 0 -1 0 0.00000 2 9 72 269 251 typeset document 4 1 1 10 0 -1 0 0.00000 2 9 75 107 101 complex attribute 4 1 1 10 0 -1 0 0.00000 2 9 73 107 209 text with markup 4 1 3 10 0 -1 0 0.00000 2 10 92 107 59 prettyprinting scanner 4 1 3 10 0 -1 0 0.00000 2 10 86 107 71 prettyprinting parser 4 0 1 10 0 -1 0 0.00000 2 9 129 41 47 flex/Bison generated functions: 4 1 3 10 0 -1 0 0.00000 2 10 142 107 164 preprocessing of format commands 4 1 3 10 0 -1 0 0.00000 2 7 76 107 146 attribute traversal 4 1 3 10 0 -1 0 0.00000 2 10 108 107 176 transformation into strings 4 0 1 10 0 -1 0 0.00000 2 9 58 41 134 output object: 4 1 3 10 0 -1 0 0.00000 2 10 83 107 257 formatting algorithm 4 0 1 10 0 -1 0 0.00000 2 9 114 41 242 document formatter (TeX): 4 2 1 10 0 -1 0 0.00000 2 9 123 401 164 language independent back end 4 2 1 10 0 -1 0 0.00000 2 9 119 401 146 language dependent front end 4 0 1 10 0 -1 0 0.00000 2 9 55 5 17 prettyprinter pretzel-2.0n-2/doc/figures/detailed-concept.fig0000644000000000000000000000360305723320712020162 0ustar rootroot#FIG 2.1 80 2 6 149 20 215 251 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 179 44 179 71 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 179 89 179 125 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 179 137 179 164 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 179 197 179 242 9999 9999 4 1 0 10 0 -1 0 0.00000 2 9 54 179 41 grammar file 4 1 0 10 0 -1 0 0.00000 2 7 51 179 83 Bison source 4 1 0 10 0 -1 0 0.00000 2 7 39 179 134 C++ code 4 1 0 10 0 -1 0 0.00000 2 9 60 179 176 prettyprinting 4 1 0 10 0 -1 0 0.00000 2 9 55 176 251 prettyprinter 4 0 3 10 0 -1 0 0.00000 2 10 29 185 59 pretzel 4 0 3 10 0 -1 0 0.00000 2 7 23 185 110 Bison 4 0 3 10 0 -1 0 0.00000 2 7 14 185 155 CC 4 1 0 10 0 -1 0 0.00000 2 7 42 179 29 formatted 4 1 0 10 0 -1 0 0.00000 2 7 25 179 188 parser -6 6 83 116 128 131 4 1 0 7 0 -1 0 0.00000 2 4 28 104 122 common 4 1 0 7 0 -1 0 0.00000 2 5 43 104 131 token header -6 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 29 44 29 74 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 29 89 29 125 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 29 140 29 167 9999 9999 2 1 0 1 -1 0 0 0 0.000 -1 1 0 0 0 1.000 4.000 8.000 29 191 29 221 170 221 9999 9999 2 1 2 1 -1 0 0 0 3.000 -1 0 0 173 98 104 98 104 113 9999 9999 2 1 2 1 -1 0 0 0 3.000 -1 1 0 0 0 1.000 4.000 8.000 104 137 104 143 35 143 9999 9999 4 1 0 10 0 -1 0 0.00000 2 7 40 29 41 token file 4 1 0 10 0 -1 0 0.00000 2 7 46 29 83 flex source 4 1 0 10 0 -1 0 0.00000 2 7 39 29 134 C++ code 4 1 0 10 0 -1 0 0.00000 2 9 60 29 176 prettyprinting 4 0 3 10 0 -1 0 0.00000 2 10 29 32 59 pretzel 4 0 3 10 0 -1 0 0.00000 2 10 15 32 110 flex 4 0 3 10 0 -1 0 0.00000 2 7 14 35 155 CC 4 0 0 10 0 -1 0 0.00000 2 9 46 74 218 is called by 4 1 0 10 0 -1 0 0.00000 2 7 42 29 29 formatted 4 1 0 10 0 -1 0 0.00000 2 5 30 29 188 scanner pretzel-2.0n-2/doc/index.list0000644000000000000000000000064506360650767014650 0ustar rootrootthis directory & These subdirectories contain the documentation of Pretzel. pretzelbook & the Pretzelbook -- the ultimate source of information on Pretzel project.report & the original report on the Pretzel project, included only for historical reasons because the information therin is old. bibliographies & the bibtex files used for the bibliography styles & various latex styles (includes also the pretzel-latex.sty) pretzel-2.0n-2/doc/index.html0000644000000000000000000000227306360650776014640 0ustar rootroot Index file for directory "pretzel/doc" of Pretzel distribution

Index file for directory "pretzel/doc" of Pretzel distribution

Files and directories are:

this directory

    These subdirectories contain the documentation of Pretzel.
pretzelbook
    the Pretzelbook -- the ultimate source of information on Pretzel
project.report
    the original report on the Pretzel project, included only for historical reasons because the information therin is old.
bibliographies
    the bibtex files used for the bibliography
styles
    various latex styles (includes also the pretzel-latex.sty)

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 10:55:27 MESZ 1997 pretzel-2.0n-2/doc/bibliographies/0000755000000000000000000000000006360651243015610 5ustar rootrootpretzel-2.0n-2/doc/bibliographies/index.list0000644000000000000000000000040306360651235017612 0ustar rootrootthis directory & some Bibliographies litprog.bib & version 1.55 of Nelson Beebe's Literate Programming Bibliography prettyprinting.bib & personal bibliography on prettyprinting supplemental.bib & supplemental bibliography for project report and PretzelBook pretzel-2.0n-2/doc/bibliographies/litprog.bib0000644000000000000000000026422406255211706017757 0ustar rootroot% /u/sy/beebe/tex/bib/litprog.bib, Wed Mar 11 07:57:40 1992 % Edit by Nelson H. F. Beebe % %%% ==================================================================== %%% BibTeX-file{ %%% author = "Nelson H. F. Beebe", %%% version = "1.55", %%% date = "08 February 1995", %%% time = "10:57:54 MST", %%% filename = "litprog.bib", %%% address = "Center for Scientific Computing %%% Department of Mathematics %%% University of Utah %%% Salt Lake City, UT 84112 %%% USA", %%% telephone = "+1 801 581 5254", %%% FAX = "+1 801 581 4148", %%% checksum = "19622 2195 10066 92230", %%% email = "beebe at eros.math.utah.edu (Internet)", %%% codetable = "ISO/ASCII", %%% keywords = "bibliography, literate programming", %%% supported = "yes", %%% docstring = "This BibTeX file records books and articles %%% about literate programming. The ISBN fields will %%% be printed if the is-alpha.bst or is-plain.bst %%% style files are used. %%% %%% CONVENTIONS %%% %%% Books are tagged by the first author's last %%% name, a colon, up to 3 upper-case letters %%% taken from the first three upper-case words %%% in the title (ignoring words like A, And, %%% The), followed by the last two digits of %%% the publication year. If there is a volume %%% entry, it is appended to the tag, prefixed %%% by a hyphen. %%% %%% For Dutch authors, a van part is included %%% in the author tag. For names with accented %%% letters, accents are dropped in the author %%% tag. %%% %%% This scheme is systematic enough that it %%% can be programmed: most of the %%% Addison-Wesley book entries were created %%% with an awk program from a dump of the AW %%% database supplied by Mona Zeftel. Older %%% entries in this bibliography were modified %%% on 28-Nov-1990 to conform to this tagging %%% scheme. %%% %%% The choice of a limit of 3 letters was %%% determined from experiments on the %%% Addison-Wesley collection. Long tags are %%% undesirable because they are a nuisance to %%% type, and also interfere with the tagged %%% bibliography output produced using the %%% LaTeX showtags style option. %%% %%% Journal article tags look like %%% author:abbrev-volume-number-page, where the %%% author part is the last name of the first %%% author: for example, VanWyk:CACM-33-3-361. %%% %%% Technical report tags look like %%% author:abbrev-number: for example, %%% Billawala:STAN-CS-89-1256. %%% %%% The Como InProceedings entries look like %%% author:TEX85-page: for example, %%% Agostini:TEX85-117. Other InProceedings %%% entries should follow a similar style. %%% %%% Entries are stored ordered by the BibTeX %%% tag name, independent of the entry type %%% (the GNU Emacs function sort-bibtex-entries %%% can be used to ensure correct ordering). %%% However, entries that are cross-referenced %%% by others are stored at the end of the %%% file, since that order is required by %%% BibTeX. %%% %%% With few exceptions, value fields for %%% acknowledgement, address, journal, and %%% publisher keywords should use macros %%% defined in the string preamble below. This %%% helps to ensure consistency, and reduces %%% the entry sizes. Address entries must %%% always include the country. %%% %%% The checksum field above contains a CRC-16 %%% checksum as the first value, followed by the %%% equivalent of the standard UNIX wc (word %%% count) utility output of lines, words, and %%% characters. This is produced by Robert %%% Solovay's checksum utility." %%% } %%% ==================================================================== %%% %%% Thanks go to: %%% Mark B. Motl for additions and corrections %%% [05-Jul-1990] %%% %%% \addtocounter{page}{36}" % was used in the report after \input bibnames @Preamble{"\input bibnames.sty " # "\hyphenation{Ker-n-i-ghan Port-able Post-Script Pren-tice Richt-er Spring-er} " } %======================================================================= % Acknowledgement abbreviations: @String{ack-bc = "S. Bart Childs, e-mail: \verb|bart@cs.tamu.edu|"} @String{ack-bnb = "Barbara N. Beeton e-mail: \verb|bnb@math.ams.com|"} @String{ack-dl = "Dave Love, e-mail: \verb|d.love@daresbury.ac.uk|"} @String{ack-eg = "Eitan M. Gurari, e-mail: \verb|gurari@cis.ohio-state.edu|"} @String{ack-ma = "M. Afzal e-mail: \verb|M.Afzal@greenwich.ac.uk|"} @String{ack-nhfb = "Nelson H. F. Beebe, Center for Scientific Computing, Department of Mathematics, University of Utah, Salt Lake City, UT 84112, USA, Tel: +1 801 581 5254, FAX: +1 801 581 4148, e-mail: \verb|beebe@math.utah.edu|"} @String{ack-nr = "Norman Ramsey, e-mail: \verb|norman@bellcore.com|"} @String{ack-pb = "Preston Briggs, e-mail: \verb|preston@cs.rice.edu|"} @String{ack-pt = "Piet Tutelaers e-mail: \verb|rcpt@urc.tue.nl|"} %======================================================================= % Journal abbreviations: @String{j-ACM-ADALET = "ACM Ada Letters"} @String{j-ACM-COMPREV = "ACM Computing Reviews"} @String{j-CACM = "Communications of the Association for Computing Machinery"} @String{j-CJ = "The Computer Journal"} @String{j-COMPLANG = "Computer Language"} @String{j-COMPUTER = "Computer"} @String{j-IEEE-SOFTWARE = "IEEE Software"} @String{j-LNCS = "Lecture Notes in Computer Science"} @String{j-OOP = "Journal of Object Oriented Programming"} @String{j-RS-MAGAZINE = "RS\slash Magazine"} @String{j-SIGPLAN = "ACM SIGPLAN Notices"} @String{j-SEJ = "Software Engineering Journal"} @String{j-SP = "Journal of Structured Programming"} @String{j-SPE = "Soft{\-}ware\emdash Prac{\-}tice and Experience"} @String{j-TEXHAX = "{\TeX{}{\-}hax}"} @String{j-TUGboat = "{\TUB{}}"} %======================================================================= % Publishers and their addresses: @String{pub-ACM = "ACM Press"} @String{pub-ACM:adr = "New York, NY 10036, USA"} @String{pub-AW = "Ad{\-d}i{\-s}on-Wes{\-l}ey"} @String{pub-AW:adr = "Reading, MA, USA"} @String{pub-BENCUM = "Benjamin/Cummings Pub. Co."} @String{pub-BENCUM:adr = "Redwood City, CA, USA"} @String{pub-IEEE-CSP = "IEEE CS Press"} @String{pub-IEEE-CSP:adr = "Los Alamitos, CA, USA"} @String{pub-MH = "McGraw-Hill"} @String{pub-MH:adr = "New York, NY, USA"} @String{pub-PH = "Pren{\-}tice-Hall"} @String{pub-PH:adr = "Englewood Cliffs, NJ 07632, USA"} @String{pub-SUCSLI = "Stanford University Center for the Study of Language and Information"} @String{pub-SUCSLI:adr = "Stanford, CA, USA"} @String{pub-SV = "Spring{\-}er-Ver{\-}lag"} @String{pub-SV:adr = "Berlin, Germany~/ Heidelberg, Germany~/ London, UK~/ etc."} @String{pub-TEXPLORATOR = "The {\TeX}plorators Corporation"} @String{pub-TEXPLORATOR:adr = "3701 W. Alabama, Suite 450-273, Houston, TX 77027, USA"} @String{pub-VNR = "Van Nostrand Reinhold"} @String{pub-VNR:adr = "New York, NY, USA"} %======================================================================= % Bibliography entries. @Article{Akiguchi:AUC92, author = "C. Akiguchi", title = "Application of {UIMS} to {CASE} environment", journal = "Joho Shori", volume = "33", number = "11", pages = "1314--1323", month = nov, year = "1992", ISSN = "0447-8053", abstract = "Discusses graphical user interfaces; interaction techniques; PERT; work breakdown structure; the X Window System; the Model-View-Controller; the EditorWidget; Adobe PostScript; XSPD*C; SPECDESSIN/SA and SPECDESSIN/FLOW; IX; and literate programming. (12 Refs.)", acknowledgement = ack-nhfb, affiliation = "Software Eng. Dev. Labs., NEC Corp., Tokyo, Japan", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6180 (User interfaces)", CODEN = "JOSHA", keywords = "User interface management systems; CASE environment; Graphical user interfaces; Interaction techniques; PERT; Work breakdown structure; X Window System; Model-View-Controller; EditorWidget; PostScript; XSPD*C; SPECDESSIN/SA; SPECDESSIN/FLOW; IX; Literate programming", language = "Japanese", thesaurus = "Graphical user interfaces; Programming environments; Software tools; User interface management systems", } @Article{Appelt:TB7-1-20, author = "W. Appelt and K. Horn", title = "{{Multiple changefiles in \WEB{}}}", journal = j-TUGboat, year = "1986", volume = "7", number = "1", pages = "20", month = Mar, } @Article{Avenarius:SIGPLAN-25-1-52, author = "Adrian Avenarius and Siegfried Oppermann", title = "{\FWEB}: {A} Literate Programming System for {Fortran 8X}", journal = j-SIGPLAN, year = "1990", volume = "25", number = "1", pages = "52--58", month = jan, ISSN = "0362-1340", abstract = "The new FWEB system applies the concept of literate programming to the FORTRAN8X language. Its design and implementation provided an opportunity to field-test WEB's applicability and provoked some reflections on its underlying concepts. (12 Refs.)", acknowledgement = ack-nhfb, affiliation = "Tech. Hochschule, Darmstadt, West Germany", bibdate = "Wed Aug 31 23:26:29 1994", classification = "C6115 (Programming support); C6140D (High level languages)", CODEN = "SINOD", keywords = "Programming tools; Structural documentation; FWEB; Literate programming system; FORTRAN8X", thesaurus = "FORTRAN; Software tools", } @InProceedings{Baecker:CHI86-51, author = "Ronald Baecker and Aaron Marcus", title = "Design Principles for the Enhanced Presentation of Computer Program Source Text", booktitle = "Proceedings {CHI}'86 (Human Factors in Computing Systems)", year = "1986", pages = "51--58", organization = "Association for Computing Machinery", address = "New York, {NY}, {USA}", month = apr, } @Book{Baecker:HFT90, author = "Ronald Baecker and Aaron Marcus", title = "Human Factors and Typography for More Readable Programs", publisher = pub-AW, year = "1990", ISBN = "0-201-10745-7", address = pub-AW:adr, } @InProceedings{Ballard:EDT89, author = "F. Ballard", booktitle = "Conference proceedings / SIGDOC 89, November 8--10, 1989, Pittsburgh Hilton and Towers, Pittsburgh, Pennsylvania", title = "`Executable' documentation: testing the documentation documenting the testing", pages_whole = "iv + 146", pages = "143--146", month = nov, year = "1989", publisher = "ACM", address = "New York, NY, USA", ISBN = "0-89791-337-X", LCCN = "QA 76.9 D6 S54 1989", abstract = "Too often documentation represents wishful thinking. It is what the designer hopes the program will do. It is what the programmer thinks the program does. It is what the customer wants the program to do. Often little effort is made to check the documentation against what the program actually does. As with many tasks performed in the program development environment, even less effort is made to automate checking the correspondence of expected, documented, results to actual results. The paper describes a modest effort to allow the computer testing of expected results against actual output in a `literate' style. (3 Refs.)", acknowledgement = ack-nhfb, affiliation = "Synectics Inc., Chicago, IL, USA", bibdate = "Sat Sep 17 11:05:18 1994", classification = "C6110 (Systems analysis and programming)", conf_date = "8--10 Nov. 1989", conf_location = "Pittsburgh, PA, USA", conf_sponsor = "ACM", keywords = "Documentation; Testing", language = "English", pub_country = "USA", thesaurus = "Program testing; System documentation", } @Article{Becker:TB7-2-109, author = "Helmut Becker", title = "{{\WEB{} system extensions}}", journal = j-TUGboat, year = "1986", volume = "7", number = "2", pages = "109", month = Jun, } @Article{Ben-Ari:j-SPE-16-10-915, author = "Mordechai Ben-Ari", title = "{FOREET}: {A} Tool for Design and Documentation of {Fortran} Programs", journal = j-SPE, volume = "16", number = "10", year = "1986", pages = "915--924", acknowledgement = ack-eg, } @Article{Bentley:CACM-29-5-364, author = "Jon Bentley", title = "Programming Pearls\emdash{}Literate Programming", journal = j-CACM, year = "1986", volume = "29", number = "5", pages = "364--369", month = may, } @Article{Bentley:CACM-29-6-471, author = "Jon Bentley and Donald E. Knuth and Doug McIlroy", title = "Programming Pearls\emdash{}{A} Literate Program", journal = j-CACM, year = "1986", volume = "29", number = "6", pages = "471--483", month = jun, } @Article{Bentley:CACM-30-4-284, author = "Jon Bentley and David Gries", title = "Programming Pearls\emdash{}Abstract data types", journal = j-CACM, year = "1987", volume = "30", number = "4", pages = "284--290", month = apr, } @Article{Bishop:SP-13-1-23, author = "Judy M. Bishop and Kevin M. Gregson", title = "Literate Programming and the {LIPED} Environment", journal = j-SP, year = "1992", volume = "13", number = "1", pages = "23--34", acknowledgement = ack-bnb # " and " # ack-pt # " and " # ack-nhfb, ISSN = "0935-1183", abstract = "The philosophy of literate programming was introduced by Donald Knuth while developing the documentation system {\TeX}. His WEB system consists of two processes, WEAVE and TANGLE, that read a specially constructed literate program source file and produce as output a file containing compilable code and a file for input into {\TeX}. WEB uses a batch approach that seems to hinder the development of new literate programs, and it has not been widely used outside its home base. The literate programming environment LIPED, described in this paper, aims to make the development of literature programs easier by being interactive (rather than batch as is WEB) and by providing instant access to a table of contents, a cross-reference table, and the extracted code. Language independence is achieved, and special facilities are made available to cater for modern programming paradigms. The system runs on minimal hardware and interfaces easily to existing compilers and text processors. This paper describes the background and progress of literate programming, compares the available literate programming systems, and provides an overview of LIPED. (18 Refs.)", affiliation = "Dept. of Comput. Sci., Univ. of Witwatersrand, Johannesburg, South Africa", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6110 (Systems analysis and programming)", CODEN = "STPGE", keywords = "LIPED environment; Literate programming; WEB system; WEAVE; TANGLE; Compilable code; Programming environment; Cross-reference table; Programming paradigms", language = "English", pub_country = "USA", thesaurus = "Programming environments; Structured programming", } @TechReport{Briggs:NUWEB-93, author = "Preston Briggs", title = "{Nuweb}, {A} Simple Literate Programming Tool", institution = "Rice University", year = "1993", type = "\verb|cs.rice.edu:/public/preston|", address = "Houston, TX", acknowledgement = ack-bc, bibdate = "Mon Oct 4 17:27:43 1993", } @PhdThesis{Brown:lit-prog-thesis, author = "Marcus E. Brown", title = "An Interactive Environment for Literate Programming", school = "Texas A\&M University", address = "College Station, TX", year = "1988", month = aug, } @InProceedings{Brown:PCE90-548, author = "Marcus E. Brown and David Cordes", title = "A Literate Programming Design Language", booktitle = "COMPEURO'90: Proceedings of the 1990 IEEE International Conference on Computer Systems and Software Engineering, May 8--10, 1990, Tel-Aviv, Israel", year = "1990", pages_whole = "xiii + 574", pages = "548--549", publisher = pub-IEEE-CSP, address = pub-IEEE-CSP:adr, ISBN = "0-8186-2041-2", LCCN = "QA76.9.S88 C66 1990", abstract = "A literate programming paradigm that provides an environment suitable for documenting and organizing the low-level design of a system is presented. It is shown that a literate program design language (PDL) strengthens the bridge design and implementation activities since the documentation generated during the design phase can be used directly as a shell for program construction. In this type of language, module names and program constructs appear as labeled modules which can be directly expanded into their equivalent code. (4 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Alabama Univ., Huntsville, AL, USA", bibdate = "Sat Sep 17 11:05:29 1994", classification = "C6115 (Programming support); C6140D (High level languages)", conf_date = "8--10 May 1990", conf_location = "Tel-Aviv, Israel", conf_sponsor = "IEEE; Inf. Processing Assoc. Israel", keywords = "Literate programming design language; Low-level design; Documentation; Program construction; Module names; Program constructs", thesaurus = "High level languages; Software tools; Specification languages", } @Article{BrinchHansen:j-SPE-24-6-579, author = "Per {Brinch Hansen}", title = "Multiple-length Division Revisited: a Tour of the Minefield", journal = j-SPE, year = "1994", volume = "24", number = "6", pages = "579--601", month = jun, note = "This paper derives an algorithm for division of long integers, and implements it as a literate program, although without identifier cross-references.", bibdate = "Wed Aug 24 15:30:29 1994", acknowledgement = ack-nhfb, } @Article{Brown:SP-11-1-11, author = "Marcus E. Brown and Bart Childs", title = "An Interactive Environment for Literate Programming", journal = j-SP, year = "1990", volume = "11", number = "1", pages = "11--25", ISSN = "0935-1183", abstract = "Interest in the field of Literate Programming is increasing, but it is not yet clear whether the WEB system for Literate Programming will receive widespread acceptance. This is due in part to the increased complexity of programming using WEB. This research concerns the development of an environment aimed at reducing the complexity of programming in WEB by creating a user interface allowing the programmer to interact more intuitively with the WEB program. (23 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Alabama Univ., Tuscaloosa, AL, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6180 (User interfaces)", CODEN = "STPGE", keywords = "Interactive environment; Literate programming; WEB; Environment; User interface; WEB program", thesaurus = "Programming environments; User interfaces", } @Article{Brown:SP-11-2-85, author = "Marcus E. Brown and David Cordes", title = "Literate Programming Applied to Conventional Software Design", journal = j-SP, year = "1990", volume = "11", number = "2", pages = "85--98", ISSN = "0935-1183", abstract = "A software maintenance costs continue to increase, greater emphasis is being placed on techniques for improving the readability and understandability of programs. The ability of the program author to present the underlying logic and design of the program plays a large role in reader comprehension of the program. The paper looks at the use of literate programming to help capture the system design within the generated code. (20 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Alabama Univ., Tuscaloosa, AL, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques)", CODEN = "STPGE", keywords = "WEB; Structured programming; Software design; Software maintenance; Readability; Understandability; Program author; Underlying logic; Literate programming; System design", thesaurus = "Software engineering; Structured programming; System documentation", } @InProceedings{Brown:HLP90, author = "M. Brown and B. Czejdo", booktitle = "{Advances in computing and information--ICCI '90 / International Conference on Computing and Information, Niagara Falls, Canada, May 23--26, 1990, Proceedings}", title = "A hypertext for literate programming", pages_whole = "vii + 529", pages = "250--259", month = may, year = "1990", publisher = pub-SV, address = pub-SV:adr, ISBN = "3-540-53504-7", LCCN = "QA75.5 .I578 1990", abstract = "The authors describe a hypertext presentation for the WEB system for literate programming. The requirements for an environment for modern literate programming are analyzed and the WEB hypertext system is proposed. Different types of windows for displaying text, indices and graphical representations are discussed. All semantic links and operators using them are analyzed. The proposed architecture of the WEB hypertext system includes a general purpose relational database management system. Mapping between hypertext queries and relational database queries is provided. The system allows the user to define new hypertext operations by providing the corresponding SQL queries for the underlying relational database. The described system can be easily extended by many other types of queries and applications. (11 Refs.)", acknowledgement = ack-eg # " and " # ack-nhfb, affiliation = "Dept. of Comput. Sci., Alabama Univ., Tuscaloosa, AL, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6180 (User interfaces); C6160D (Relational DBMS)", conf_date = "23--26 May 1990", conf_location = "Niagara Falls, Ont., Canada", conf_sponsor = "Natural Sci. Eng. Res. Council of Canada; Carleton Univ.; Laurentian Univ", editor = "Selim G. Akl and F. Fiala and Waldemar W. Koczkodaj", keywords = "Hypertext; Literate programming; WEB system; Windows; Graphical representations; Semantic links; Relational database management system; Hypertext queries; SQL queries", thesaurus = "Hypermedia; Programming environments; Relational databases; User interfaces", } @Article{Childs:TB-13-3-261, author = "Bart Childs", title = "Literate Programming, {A} Practitioner's View", journal = j-TUGboat, year = "1992", volume = "13", number = "3", pages = "261--268", month = oct, acknowledgement = ack-bc, bibdate = "Mon Oct 4 17:21:07 1993", } @TechReport{Childs:LP92, author = "Bart Childs", title = "An Introduction to the {WEB} Style of Literate Programming", institution = "Texas A\&M University", year = "1992", type = "\verb|ftp.cs.tamu.edu:/pub/tex-web/web/DOCs|", address = "College Station, TX", acknowledgement = ack-bc, bibdate = "Mon Oct 4 17:21:07 1993", } @TechReport{Childs:LP93, author = "Bart Childs", title = "{GNU} {Emacs} Reference Card (with web-mode)", institution = "Texas A\&M University", year = "1993", type = "\verb|ftp.cs.tamu.edu:/pub/tex-web/web/DOCs|", address = "College Station, TX", acknowledgement = ack-bc, bibdate = "Wed Aug 24 17:50:54 1994", } @Article{Copeland:ILP95, author = "Jeffrey Copeland and Jeffrey Haemer", title = "An Introduction to Literate Programming", journal = j-RS-MAGAZINE, year = "1995", volume = "4", number = "1", pages = "26--30", month = jan, acknowledgement = ack-nhfb, bibdate = "Fri Jan 27 13:45:03 1995", } @Article{Cordes:COMPUTER-24-6-52, author = "David Cordes and Marcus Brown", title = "The Literate-Programming Paradigm", journal = j-COMPUTER, year = "1991", volume = "24", number = "6", pages = "52--61", month = jun, ISSN = "0018-9162", abstract = "Literate programming, a technique for coding software systems that promotes readability and comprehension, is examined in detail. The current literate-programming paradigm is reviewed by looking at two sample literate programs. A critique of literate programming as it is currently used is presented, and methods for enhancing the process are explored. A number of new facilities are proposed, and restrictions on current literate-programming practices are suggested. (11 Refs.)", acknowledgement = ack-nhfb, affiliation = "Alabama Univ., Tuscaloosa, AL, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming)", CODEN = "CPTRB", keywords = "Coding software systems; Literate-programming paradigm", thesaurus = "Programming", } @Article{Denning:CACM-30-7-593, author = "Peter J. Denning", title = "Announcing Literate Programming", journal = j-CACM, year = "1987", volume = "30", number = "7", pages = "593", month = jul, } @Article{Fox:TB11-4-511-513, author = "Jim Fox", title = "{{Webless literate programming}}", journal = j-TUGboat, year = "1990", volume = "11", number = "4", pages = "511--513", month = Nov, } @Book{Fraser:RCC95, author = "Chris W. Fraser and David R. Hanson", title = "A Retargetable {C} Compiler: Design and Implementation", publisher = pub-BENCUM, address = pub-BENCUM:adr, year = "1995", ISBN = "0-8053-1670-1", LCCN = "QA76.73.C15F75 1995", note = "From the authors' announcement: ``\ldots this book is an example of a `literate program.' Like {\em {\TeX}: The Program\/} by D. E. Knuth (Addison-Wesley, 1986), this book is lcc's source code and the prose that describes it. The code is presented in the order that best suits understanding, not in the order dictated by the C programming language. The source code that appears on the diskette is extracted automatically from the book's text files. \ldots{} The distribution is available via `anonymous' ftp from \verb=ftp.cs.princeton.edu= \verb=(128.112.152.13)= in the directory \verb=pub/lcc=. \ldots{} Additional information about lcc and about our book is available on the WWW at URL \verb=http://www.cs.princeton.edu/software/lcc=.''", pages = "xv + 564", price = "US\$55.95", acknowledgement = ack-nhfb, bibdate = "Wed Feb 08 10:55:34 1995", } @Article{Guntermann:TB7-3-134-2, author = "Klaus Guntermann and Joachim Schrod", title = "{{\WEB\ adapted to C}}", journal = j-TUGboat, year = "1986", volume = "7", number = "3", pages = "134--137", month = Oct, } @InProceedings{Gurari:WLP91, author = "E. M. Gurari and J. Wu", booktitle = "1991 ACM Computer Science Conference: March 5--7, 1991, San Antonio Convention Center, San Antonio, Texas: Proceedings: Preparing for the 21st Century", title = "A {WYSIWYG} literate programming system (preliminary report)", pages_whole = "xxix + 711", pages = "94--104", month = mar, year = "1991", publisher = "ACM", address = "New York, NY, USA", ISBN = "0-89791-382-5", LCCN = "QA75.5 .A137 1991", abstract = "Conceptually, literate programming systems are document preparation systems that are augmented with features for writing programs. They offer features for identifying the different components of the programs, for highlighting the relations that exist between the components, and for explaining the components and the relations. The authors introduce a literate programming system that is based on a hierarchical variation of MacWrite. The system distinguishes code from prose by the fonts that they are written in, uses boxes for abstracting and structuring code, and employs ports for generating different views of the code. (19 Refs.)", acknowledgement = ack-eg # " and " # ack-nhfb, affiliation = "Dept. of Comput. and Inf. Sci., Ohio State Univ., Columbus, OH, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6110 (Systems analysis and programming)", conf_date = "5--7 March 1991", conf_location = "San Antonio, TX, USA", keywords = "Program writing; WYSIWYG; Literate programming systems; Document preparation systems; Hierarchical variation; MacWrite; Prose; Fonts; Boxes; Abstracting; Structuring code; Ports", thesaurus = "Programming; Programming environments; Software tools", } @Book{Gurari:TLD94, author = "Eitan M. Gurari", title = "{\TeX} and {\LaTeX}: Drawing and Literate Programming", publisher = pub-MH, ISBN = "0-07-025208-4", LCCN = "Z253.4.T47G87, 686.2'2544536-dc20, 93-8603 CIP", year = "1994", address = pub-MH:adr, keywords = "TeX (computer file); computerized typesetting; mathematics printing -- computer programs", price = "US\$34.95", series = "McGraw-Hill programming tools for scientists and engineers", bibdate = "Fri Aug 19 00:24:55 1994", acknowledgement = ack-nhfb, } @Article{Hamilton:CACM-31-12-1376, author = "Eric Hamilton", title = "Literate Programming\emdash{}Expanding Generalized Regular Expressions", journal = j-CACM, year = "1988", volume = "31", number = "12", pages = "1376--1385", month = dec, } @Article{Hanson:CACM-30-7-594, author = "David R. Hanson", title = "Literate Programming\emdash{}Printing Common Words", journal = j-CACM, year = "1987", volume = "30", number = "7", pages = "594--599", month = jul, } @Book{Holub:CDC90, author = "Allen I. Holub", title = "Compiler Design in {C}", publisher = pub-PH, address = pub-PH:adr, year = "1990", note = pub-PH # " Software Series, Editor: Brian W. Kernighan.", ISBN = "0-13-155045-4", LCCN = "QA76.76.C65 H65 1990", pages = "xviii + 924", bibdate = "Wed Dec 15 09:13:20 1993", } @MastersThesis{Houser:LLP92, author = "Christopher Driessen Houser", title = "A literate {Lisp} programming environment", pages = "viii + 93", school = "Department of Computer Science, University of California, Los Angeles", LCCN = "LD 791.8 C6 H817 1992", address = "Los Angeles, CA, USA", year = "1992", acknowledgement = ack-nhfb, bibdate = "Fri Aug 19 00:23:48 1994", keywords = "dissertations, academic -- UCLA -- computer science", note = "Typescript (photocopy).", } @Article{Hyman:COMPLANG-7-7-67, author = "Marco S. Hyman", title = "Literate {C++}", journal = j-COMPLANG, year = "1990", volume = "7", number = "7", pages = "67--68, 70, 72, 74--77, 79", month = jul, ISSN = "0749-2839", abstract = "The author discusses the application of literate programming to object-oriented C++. He develops an Awk preprocessor to store documentation along with source code. The information can be extracted just before compilation. (2 Refs.)", acknowledgement = ack-nhfb, bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6140D (High level languages); C6150C (Compilers, interpreters and other processors)", CODEN = "CSAEE", keywords = "Literate programming; Object-oriented C++; Awk preprocessor; Store documentation; Source code; Compilation", thesaurus = "C language; C listings; Object-oriented programming; Program processors; Software tools; System documentation", } @Article{Jackson:CACM-30-12-1000, author = "Michael A. Jackson", title = "Literate Programming\emdash{}Processing Transactions", journal = j-CACM, year = "1987", volume = "30", number = "12", pages = "1000--1010", month = dec, } @Article{Kennedy:TB9-2-124-125, author = "David Kennedy", title = "{{\TeX\ adapted to \CWEB{}}}", journal = j-TUGboat, year = "1988", volume = "9", number = "2", pages = "124--125", month = Aug, } @Article{Knuth:CJ-27-2-97, author = "Donald E. Knuth", title = "Literate Programming", journal = j-CJ, year = "1984", volume = "27", number = "2", pages = "97--111", month = may, acknowledgement = ack-nhfb, bibdate = "Wed Aug 24 17:14:45 MDT 1994", keywords = "design; human factors; languages", review = "ACM CR 8501-0018", subject = "D.2.7 Software, SOFTWARE ENGINEERING, Distribution and Maintenance, Documentation \\ I.7.1 Computing Methodologies, TEXT PROCESSING, Text Editing, Languages \\ H.1.2 Information Systems, MODELS AND PRINCIPLES, User/Machine Systems, Human factors \\ D.3 Software, PROGRAMMING LANGUAGES, Language Constructs \\ I.7.1 Computing Methodologies, TEXT PROCESSING, Text Editing, WEB", } @Book{Knuth:CSS93, author = "Donald E. Knuth and Silvio Levy", title = "The {CWEB} System of Structured Documentation, Version 3.0", publisher = pub-AW, year = "1993", ISBN = "0-201-57569-8", LCCN = "QA76.9.D3 K6 1993", address = pub-AW:adr, acknowledgement = ack-nhfb, bibdate = "Thu Dec 16 09:04:49 1993", } @Book{Knuth:ct-b, author = "Donald E. Knuth", title = "{\TeX}: The Program", publisher = pub-AW, year = "{\noopsort{1986b}}1986", volume = "B", series = "Computers \& Typesetting", address = pub-AW:adr, ISBN = "0-201-13437-3", bibdate = "Wed Aug 24 17:44:17 1994", } @Book{Knuth:ct-d, author = "Donald E. Knuth", title = "{\MF}: The Program", publisher = pub-AW, year = "{\noopsort{1986d}}1986", volume = "D", series = "Computers \& Typesetting", address = pub-AW:adr, ISBN = "0-201-13438-1", } @Book{Knuth:LP92, author = "Donald E. Knuth", title = "Literate Programming", publisher = pub-SUCSLI, address = pub-SUCSLI:adr, series = "CSLI Lecture Notes Number 27", keywords = "electronic digital computers -- programming", year = "1992", ISBN = "0-937073-80-6 (paper), 0-937073-81-4 (cloth)", LCCN = "QA76.6.K644", pages = "xv + 368", acknowledgement = ack-nhfb, bibdate = "Fri Aug 19 00:24:20 1994", } @Article{Knuth:TB12-2-313, author = "Donald Knuth", title = "{{Fixed-point glue setting: Errata}}", journal = j-TUGboat, year = "1991", volume = "12", number = "2", pages = "313", month = Jun, } @Article{Knuth:TB3-1-10, author = "Donald Knuth", title = "{{Fixed-point glue setting\emdash{}an example of {\tt WEB}}}", journal = j-TUGboat, year = "1982", volume = "3", number = "1", pages = "10", month = Mar, } @TechReport{Knuth:web83, author = "Donald E. Knuth", title = "The {\WEB{}} System of Structured Documentation", institution = "Stanford University", year = "1983", type = "Stanford Computer Science Report", number = "{CS}980", address = "Stanford, {CA}", month = sep, } @Book{Knuth:SGB93, author = "Donald E. Knuth", title = "The {Stanford} {GraphBase}: {A} Platform for Combinatorial Computing", publisher = pub-ACM, year = "1993", address = pub-ACM:adr, price = "US\$45.25", note = "[From the publisher]: \ldots{} represents Knuth's final preparation for Volume 4 of {\em The Art of Computer Programming}. Through the use of about 30 examples, the book demonstrates the art of literate programming. Each example is a programmatic essay, a short story that can be read by human beings, as well as read and interpreted by machines. In these essays/programs, Knuth makes new contributions to the exposition of several important algorithms and data structures.", pages = "vii + 576", ISBN = "0-201-54275-7", LCCN = "QA164 .K6 1993", acknowledgement = ack-pb, bibdate = "Wed Aug 24 17:44:04 1994", } @Article{Knuth:MLP94, author = "D. E. Knuth", title = "Mini-indexes for literate programs", journal = "Software--Concepts and Tools", volume = "15", number = "1", pages = "2--11", month = "", year = "1994", ISSN = "0945-8115", abstract = "The author describes how to implement a documentation technique that helps readers to understand large programs or collections of programs, by providing local indexes to all identifiers that are visible on every two-page spread. A detailed example is given for a program that finds all Hamiltonian circuits in an undirected graph. (11 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Stanford Univ., CA, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C1160 (Combinatorial mathematics)", CODEN = "SCOTE", keywords = "Mini-indexes; Literate programs; Documentation technique; Large programs; Hamiltonian circuits; Undirected graph; WEB; CWEB; CTWILL; Hypertext", thesaurus = "Graph theory; Indexing; Programming; System documentation", } @InProceedings{Kortright:CCT92, author = "E. Kortright and D. Cordes", booktitle = "Proceedings / IEEE Southeastcon '92, April 12--15, 1992, Birmingham, Alabama", title = "Cnest and Cscope: Tools for the literate programming environment", pages_whole = "lii + 846", pages = "604--609 (vol. 2)", month = apr, year = "1992", publisher = "IEEE", address = "New York, NY, USA", ISBN = "0-7803-0494-2", LCCN = "TK5 .I32 1992 v.1-2", abstract = "The authors describe two tools for the literate programming language Cweb: Cnest and Cscope. Cweb is a Web programming environment for the programming language C using the typesetting program T/sub E/X. An overview of Web is given. Cnest and Cscope operate within the EMACS editing environment and provide support both for the program developer and for the maintenance programmer. Their implementations are discussed in detail. (6 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Alabama Univ., Tuscaloosa, AL, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support); C6140D (High level languages)", conf_date = "12--15 April 1992", conf_location = "Birmingham, AL, USA", conf_sponsor = "IEEE", keywords = "TEX; Literate programming environment; Cweb; Cnest; Cscope; Web programming environment; C; Typesetting program; EMACS editing environment; Program developer; Maintenance programmer", note = "2 vol.", thesaurus = "C language; Programming environments; Software tools; Text editing", } @Article{Krommes:fortran-web, author = "John Krommes", title = "{\FWEB} ({Krommes}) vs. {\FWEB} ({Avenarius} and {Oppermann})", journal = j-TEXHAX, year = "1990", volume = "90", number = "19", month = feb, } @Article{Lecarme:j-ACM-COMPREV-26-1-75, author = "O. Lecarme", title = "Literate Programming", journal = j-ACM-COMPREV, volume = "26", number = "1", year = "1985", pages = "75", acknowledgement = ack-eg, } @Article{Levy:TB8-1-12, author = "Silvio Levy", title = "{{\WEB{} adapted to C, another approach}}", journal = j-TUGboat, year = "1987", volume = "8", number = "1", pages = "12--13", month = Apr, } @Article{Levy:j-COMPLANG-10-1-67, author = "Silvio Levy", title = "Literate Programming and {Cweb}", journal = j-COMPLANG, year = "1993", volume = "10", number = "1", pages = "67--68, 70", month = jan, bibdate = "Thu Dec 3 09:11:03 1992", } @Article{Lindsay:CACM-32-6-740, author = "Donald C. Lindsay", title = "Literate Programming\emdash{}{A} File Difference Program", journal = j-CACM, year = "1989", volume = "32", number = "6", pages = "740--755", month = jun, } @Article{Lins:JSP-10-1-60, author = "Charles Lins", title = "A First Look at Literate Programming", journal = j-SP, year = "1989", volume = "10", number = "1", pages = "60--62", ISSN = "0935-1183", abstract = "The author provides background material about literate programming and why this concept is important. He gives the background material on the nature and of the problem and traditional solutions, and a brief overview of literate programming and how it addresses the problem. He examines the WEB system, a literate programming tool, and provides a commentary on some literate programming issues. (7 Refs.)", acknowledgement = ack-nhfb, affiliation = "Apple Comput. Inc., Cupertino, CA, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming)", CODEN = "STPGE", keywords = "Literate programming", thesaurus = "Programming; System documentation", } @Article{Lins:JSP-10-2-107, author = "Charles Lins", title = "An Introduction to Literate Programming", journal = j-SP, year = "1989", volume = "10", number = "2", pages = "107--112", ISSN = "0935-1183", abstract = "The author discusses D. E. Knuth's concept of literate programming. He covers the particulars of the literate programming style as described by Knuth in Computers and Typesetting, vol. B, {\TeX}, The Program (1986). He concludes with a sample literate program-using Modula-2 as an alternative to Pascal-describing the interface to the relation abstract data type from the domain of relational database theory. (5 Refs.)", acknowledgement = ack-nhfb, affiliation = "Apple Comput. Inc., Cupertino, CA, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming)", CODEN = "STPGE", keywords = "Structured programming; Literate programming; Programming style; Modula-2; Relation abstract data type; Relational database theory", thesaurus = "Structured programming", } @Article{Mittelbach:j-TUGboat-9-3-298, author = "Frank Mittelbach", title = "A New Implementation of the Array- and Tabular- Environments", journal = j-TUGboat, volume = "9", number = "3", year = "1988", pages = "298--314", acknowledgement = ack-eg, } @PhdThesis{Motl:LPE90, author = "Mark B. Motl", title = "A Literate Programming Environment Based on an Extensible Editor", school = "Texas A\&M University", year = "1990", address = "College Station, {TX}", month = dec, acknowledgement = ack-bc, bibdate = "Mon Oct 4 17:21:07 1993", } @TechReport{Motl:UMG91, author = "Mark B. Motl and Bart Childs", title = "A User's Manual for {GNU} {Emacs}' Web-mode", institution = "Texas A\&M University", year = "1991", type = "\verb|ftp.cs.tamu.edu:/pub/tex-web/web/DOCs|", address = "College Station, {TX}", acknowledgement = ack-bc, bibdate = "Wed Aug 24 17:50:49 1994", } @Article{Naeve:HMT91, author = "P. Naeve and D. Trenkler and H. P. Wolf", title = "How to make the teaching of statistics roar. Some thoughts on computer based experiments", journal = "Computational Statistics Quarterly", volume = "6", number = "4", pages = "325--353", month = "", year = "1991", abstract = "The application of computers in teaching statistics offers new possibilities. Two kinds of experiments are introduced. Firstly, experiments to demonstrate statistical concepts by exploiting the graphical capabilities of computers. Secondly, experiments which may help teach data analysis strategies. Examples for both kinds are given. First steps towards experiment construction are developed. The usefulness of Literate APL is demonstrated too. (13 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Econ., Bielefeld Univ., Germany", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C7810C (Computer-aided instruction); C7310 (Mathematics)", CODEN = "CSQUE", keywords = "Computer based experiments; Computers; Teaching statistics; Statistical concepts; Graphical capabilities; Data analysis; Experiment construction; Literate APL", thesaurus = "Computer aided instruction; Statistical analysis", } @InProceedings{Naeve:APT93, author = "P. Naeve and B. Strohmeier and P. Wolf", booktitle = "International Conference on APL", title = "{APL} programming without tears to it is time for a change", journal = "APL Quote Quad", volume = "24", number = "1", pages = "185--189", month = aug, year = "1993", ISSN = "0163-6006", abstract = "To overcome the unreadability of traditional APL-code, D. E. Knuth's (1984) idea of literate programming is adapted to APL. The APL2WEB system of structured documentation is introduced as a new way of APL-programming. An example is given to highlight the merits of this combination. (8 Refs.)", acknowledgement = ack-nhfb, affiliation = "Fakultat fur Wirtschaftswissenschaften, Bielefeld Univ., Germany", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming); C6140D (High level languages); C0310F (Software development management)", CODEN = "APLQD", conf_date = "15--19 Aug. 1993", conf_location = "Toronto, Ont., Canada", conf_sponsor = "ACM", keywords = "APL programming; Unreadability; Traditional APL-code; Knuth; Literate programming; APL2WEB system; Structured documentation", thesaurus = "APL; Programming; System documentation", } @Article{Oman:CACM-33-5-506, author = "Paul W. Oman and Curtis Cook", title = "Typographic Style is More than Cosmetic", journal = j-CACM, year = "1990", volume = "33", number = "5", pages = "506--520", month = may, } @Article{Oman:IEEESOFTWARE-7-1-39, author = "Paul W. Oman and Curtis Cook", title = "The Book Paradigm for Improved Maintenance", journal = j-IEEE-SOFTWARE, year = "1990", volume = "7", number = "1", pages = "39--45", month = jan, } @PhdThesis{Oman:oman88a, author = "Paul W. Oman", title = "A Taxonomic Analysis of Typographic Programming Style", school = "Oregon State University", year = "1988", address = "Corvallis, {OR}", month = dec, } @TechReport{Oman:OSUTR-88-60-20, author = "Paul W. Oman and Curtis Cook", title = "A Programming Style Taxonomy", institution = "Oregon State University", year = "1988", type = "Technical Report", number = "88-60-20", address = "Corvallis, {OR}", } @Article{Oman:SIGPLAN-23-12-69, author = "P. W. Oman and C. R. Cook", title = "A paradigm for programming style research", journal = j-SIGPLAN, volume = "23", number = "12", pages = "69--78", month = dec, year = "1988", ISSN = "0362-1340", acknowledgement = ack-nhfb, bibdate = "Sat Aug 13 17:16:20 MDT 1994", keywords = "measurement; experimentation; performance; design; languages", subject = "D.1.m Software, PROGRAMMING TECHNIQUES, Miscellaneous", } @InProceedings{Pappas:proc-ada-tech90-500, author = "T. L. Pappas", title = "Literate Programming for Reusability: {A} Queue Package Example", booktitle = "Proceedings of the Eighth Annual Conference on {Ada} Technology", year = "1990", pages_whole = "xiv + 669", pages = "500--514", organization = "ANCOST, Inc. (Sponsor)", address = "Atlanta, Georgia, USA", month = mar, abstract = "Writing reusable software components requires more than just following coding guidelines. It also requires that potential clients of a component can easily understand the documentation associated with the component. Literate programming, as suggested by D. Knuth (1983), is concerned with combining code and documentation in a form that is more easily read by humans, rather than by compilers. The paper illustrates the benefits of a literate programming approach to writing reusable software by presenting a generic package written in a literate programming style. ADA WEB, a language for literate programming that combines Ada and TEX, was used to prepare the paper. (14 Refs.)", review = "This paper begins with a set of guidelines for writing and documenting reusable Ada software. {\tt AdaWeb}, a literate programming system combining Ada and {\TeX} is described. A sample {\tt AdaWeb} package, {\em Bounded Generic Queue Package}, is provided. Features of {\tt AdaWeb} are explained as they are used in the literate program.", acknowledgement = ack-nhfb, affiliation = "Intermetrics Inc., Warminster, PA, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques)", conf_date = "5--8 March 1990", conf_location = "Atlanta, GA, USA", conf_sponsor = "Ancost", keywords = "Queue package; Software components; Documentation; Literate programming; Generic package; ADA WEB; Ada; TEX", thesaurus = "Ada; Programming; Software reusability; System documentation", } @InCollection{Pepper:LPD91, author = "P. Pepper", title = "Literate program derivation: a case study", crossref = "Broy:MPS91", pages = "101--124", year = "1991", abstract = "`Literate programming' is a notion that has been introduced by D. E. Knuth (1984), as a means for improving the art of programming by amalgamating explanatory text with the program proper. The author combines the principal ideas of literate programming with the concepts of formal program development, based on algebraic specifications and transformations. This experiment is performed using the sublinear string-searching algorithm of R. S. Boyer and J. S. Moore (1977) as an illustrating example. (17 Refs.)", acknowledgement = ack-nhfb, affiliation = "Inst. fur Angewandte Inf., Tech. Univ., Berlin, Germany", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C5260B (Computer vision and picture processing); C1250 (Pattern recognition); C4240 (Programming and algorithm theory)", keywords = "Case study; Explanatory text; Literate programming; Formal program development; Algebraic specifications; Transformations; Sublinear string-searching algorithm", thesaurus = "Computerised pattern recognition; Formal specification; Programming", } @Book{PeytonJones:IFL92, author = "Simon L. {Peyton Jones} and David R. Lester", title = "Implementing functional languages", publisher = pub-PH, year = "1992", address = pub-PH:adr, ISBN = "0-13-721952-0", price = "US\$42.00", acknowledgement = ack-dl, bibdate = "Thu Aug 26 10:51:16 1993", note = "Presents literate programs in {\TeX} and Miranda.", } @Book{Plauger:SCL92, author = "P. J. Plauger", title = "The {Standard C} Library", publisher = pub-PH, address = pub-PH:adr, year = "1992", ISBN = "0-13-838012-0", LCCN = "QA76.73.C15 P563 1991", pages = "xiv + 498", bibdate = "Wed Dec 15 10:40:47 1993", } @Article{Ramsdell:TEXHAX-88-39, author = "J. D. Ramsdell", title = "{Scheme\TeX}\emdash Simple support for literate programming in {Lisp}", journal = j-TEXHAX, year = "1988", volume = "88", number = "39", month = apr, bibdate = "Wed Aug 24 17:43:40 1994", } @Article{Ramsey:CACM-32-9-1051, author = "Norman Ramsey", title = "Weaving a Language-Independent {{\WEB}}", journal = j-CACM, year = "1989", volume = "32", number = "9", pages = "1051--1055", month = sep, } @Article{Ramsey:j-SPE-21-7-677, author = "Norman Ramsey and Carla Marceau", title = "Literate Programming on a Team Project", journal = j-SPE, year = "1991", volume = "21", number = "7", pages = "677--683", month = jul, ISSN = "0038-0644", abstract = "Literate programming on a team project was used to write a 33000 line program for the Synthesizer Generator. The program, Penelope, was written using WEB, a tool designed for writing literate programs. Unlike other WEB programs, many of which have been written by WEB's developer or by individuals, Penelope was not intended to be published. The authors used WEB in the hope that both their team and its final product would benefit from the advantages often attributed to literate programming. The WEB source served as good internal documentation throughout development and maintenance, and it continues to document Penelope's design and implementation. This experience also uncovered a number of problems with WEB. (33 Refs.)", acknowledgement = ack-bnb # " and " # ack-nhfb, affiliation = "Odyssey Res. Associates, Ithaca, NY, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C7820 (Humanities); C6110 (Systems analysis and programming); C7106 (Word processing); C6130D (Document processing techniques)", CODEN = "SPEXB", keywords = "Literature programming; Team project; Synthesizer Generator; Penelope; WEB; Literate programs; Literate programming; Internal documentation", thesaurus = "Linguistics; Literature; Programming; Word processing", } @TechReport{Ramsey:LPT92, author = "Norman Ramsey", title = "Literate-Programming Tools Need Not Be Complex", institution = "Department of Computer Science, Princeton University", year = "1992", number = "CS-TR-351-91", keywords = "literate programming, readability, programming languages", month = aug, note = "Submitted to {\em IEEE Software}.", type = "Report at \verb|ftp.cs.princeton.edu| in \verb|/reports/1991/351.ps.Z|. Software at \verb|ftp.cs.princeton.edu| in \verb|/pub/noweb.shar.Z| and at \verb|bellcore.com| in \verb|/pub/norman/noweb.shar.Z|.", bibdate = "Tue Oct 12 10:28:45 1993", acknowledgement = ack-bc # " and " # ack-nr, } @Article{Ramsey:j-IEEE-SOFTWARE-11-5-97, author = "Norman Ramsey", title = "Literate Programming Simplified", journal = j-IEEE-SOFTWARE, year = "1994", volume = "11", number = "5", pages = "97--105", month = sep, acknowledgement = ack-nhfb, bibdate = "Wed Sep 07 20:28:11 1994", } @Article{Reenskaug:j-SIGPLAN-24-10-337, author = "Trygve Reenskaug and Anne Lise Skaar", title = "An environment for literate {Smalltalk} programming", journal = j-SIGPLAN, volume = "24", number = "10", pages = "337--345", month = oct, year = "1989", ISSN = "0362-1340", acknowledgement = ack-nhfb, abstract = "The programming environment described in this paper is an adaptation of Donald Knuth's concept of literate programming, applied to Smalltalk programs. The environment provides a multi-media document production system including media for Smalltalk class and method definitions.\par There are two outputs from the system. The first output is a document which contains general descriptions and discussions intermixed with precise definitions of program fragments, test inputs and test results. The second output consists of compiled Smalltalk programs installed and ready for execution.\par The main idea was to produce program documentation that was just as interesting and fascinating to read as ordinary literature. Our experience showed an added benefit, namely that the literate programming environment was an active aid in the problem solving process. The simultaneous programming and documentation lead to significantly improved quality of both programs and documentation.", bibdate = "Wed Aug 31 23:24:32 1994", classification = "C6115 (Programming support)", CODEN = "SINOD", conf_date = "1--6 Oct. 1989", conf_location = "New Orleans, LA, USA", conf_sponsor = "ACM", keywords = "design; documentation; languages; reliability; Class definitions; Programming environment; Literate programming; Smalltalk programs; Multi-media document production system; Method definitions; Program fragments; Test inputs; Test results; Compiled Smalltalk programs; Program documentation; Problem solving process", subject = "D.2.6 Software, SOFTWARE ENGINEERING, Programming Environments \\ D.3.2 Software, PROGRAMMING LANGUAGES, Language Classifications, Smalltalk-80 \\ D.2.7 Software, SOFTWARE ENGINEERING, Distribution and Maintenance, Documentation \\ D.2.5 Software, SOFTWARE ENGINEERING, Testing and Debugging \\ D.1.0 Software, PROGRAMMING TECHNIQUES, General \\ D.2.2 Software, SOFTWARE ENGINEERING, Tools and Techniques, User interfaces", thesaurus = "Object-oriented programming; Programming environments; Smalltalk; System documentation", } @Article{Sametinger:j-OOP-4-8-24, author = "J. Sametinger", title = "A Hypertext System for Literate {C}++ Programming", journal = j-OOP, volume = "4", number = "8", year = "1992", pages = "24--29", acknowledgement = ack-eg # " and " # ack-nhfb, ISSN = "0896-8438", abstract = "Programs are written to be executed by computers rather than read by humans. This complicates program comprehension, which plays a major role in software maintenance. Literate programming is an approach to improve program understanding by regarding programs as works of literature. The authors present a tool that supports literate programming in C++, based on a hypertext system. (18 Refs.)", affiliation = "Inst. fur Wirtschaftsinf., Johannes Kepler Univ. of Linz, Austria", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C6140D (High level languages); C6160Z (Other DBMS)", CODEN = "JOOPE", keywords = "Literate C++ programming; Program comprehension; Software maintenance; Program understanding; Hypertext system", thesaurus = "C language; Hypermedia; Programming; Software maintenance", } @InProceedings{Sennett:DCA92, author = "C. T. Sennett", booktitle = "5th Refinement Workshop: Proceedings of the 5th Refinement Workshop, organized by BCS-FACS, London, 8--10 January 1992", title = "Demonstrating the compliance of Ada programs with {Z} specifications", pages_whole = "viii + 378", pages = "70--87", month = jan, year = "1992", publisher = pub-SV, address = pub-SV:adr, ISBN = "3-540-19752-4", LCCN = "QA76.76.D47 R44 199", abstract = "The paper describes a notation for presenting a claim that a program written in Ada satisfies a specification written in Z. The notation has both formal and informal elements: the formal elements follow the style of the refinement calculus, while the informal elements follow Knuth's (1984) literate programming style. The combination of formal and informal elements allows for selective verification, an important requirement for practical use of formal refinement. (12 Refs.)", acknowledgement = ack-nhfb, affiliation = "Defence Res. Agency, Malvern, UK", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C4210 (Formal logic)", conf_date = "8--10 Jan. 1992", conf_location = "London, UK", editor = "Cliff B. Jones and Roger C. Shaw and Tim Denvir", keywords = "Ada programs; Z specifications; Refinement calculus; Literate programming; Selective verification; Formal refinement", language = "English", pub_country = "Germany", thesaurus = "Ada; Formal specification; Formal verification; Specification languages", } @Article{Sewell:TB8-2-118, author = "E. Wayne Sewell", title = "{{How to {\tt MANGLE} your software: the \WEB{} system for Modula-2}}", journal = j-TUGboat, year = "1987", volume = "8", number = "2", pages = "118--122", month = Jul, } @Article{Sewell:TB8-2-123, author = "E. Wayne Sewell", title = "{{The {\tt SCANTEX} processor}}", journal = j-TUGboat, year = "1987", volume = "8", number = "2", pages = "123--128", month = Jul, } @Book{Sewell:WPL89, author = "E. Wayne Sewell", title = "Weaving a Program: Literate Programming in {\WEB}", publisher = pub-VNR, address = pub-VNR:adr, keywords = "web (computer program language)", pages = "xx + 556", year = "1989", ISBN = "0-442-31946-0", LCCN = "QA76.73.W24 S491 1989", bibdate = "Fri Aug 19 00:20:22 1994", } @Article{Shum:SEJ-8-3-113, author = "Stephen Shum and Curtis Cook", title = "{AOPS}: an Abstraction-Oriented Programming System for Literate Programming", journal = j-SEJ, year = "1993", volume = "8", number = "3", pages = "113--120", month = may, acknowledgement = ack-ma, } @Article{Smith:ABL91, author = "L. M. C. Smith and M. H. Samadzadeh", title = "An annotated bibliography of literate programming", journal = j-SIGPLAN, volume = "26", number = "1", pages = "14--20", month = jan, year = "1991", ISSN = "0362-1340", abstract = "Although literate programming can be considered a programming style, it would better be categorized asa new programming paradigm. The entries in this bibliography illustrate the recent growth of research and interest in the area of literate programming. (32 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Oklahoma State Univ., Stillwater, OK, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming)", CODEN = "SINOD", keywords = "Literate programming; Programming style; Programming paradigm; Bibliography", thesaurus = "Programming", } @Article{Smith:SP-13-1-35, author = "Lisa M. Smith and Mansur H. Samadzadeh", title = "Measuring Complexity and Stability of {WEB} programs", journal = j-SP, year = "1992", volume = "13", number = "1", pages = "35--50", acknowledgement = ack-pt # " and " # ack-nhfb, ISSN = "0935-1183", abstract = "Software maintenance engineers spend at least half of their time trying to understand the system they are to modify. This is due partially to the fact that often the only documentation available is the source code itself. The literate programming paradigm provides the incentive and the capability to produce high quality code and documentation simultaneously. The goal is to create `works of literature' which have all the extras (table of contents, cross references, and indexes) to help readers to comprehend the programs quickly and thoroughly. The purpose of this research is to explore the viability of application of the measurements of software complexity and stability of traditionally developed code to literature programs. A literature program, the WEBmeter, was developed to collect some of the well-known metrics, originally defined for conventional software, for literature programs. Other design and stability metrics were manually extracted from the TANGLEd version of the input WEB programs. Some observations about ten programs that were subjected to the metrics/stability analysis are included. (37 Refs.)", affiliation = "Dept. of Comput. Sci., Oklahama State Univ., Stillwater, OK, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C0310F (Software development management)", CODEN = "STPGE", keywords = "Complexity measurement; Software maintenance; Stability; WEB programs; Literate programming paradigm; Documentation; Cross references; Indexes; Software complexity; WEBmeter; Metrics", thesaurus = "Software maintenance; Software metrics; Structured programming", } @InProceedings{Snelting:PTS90, author = "G. Snelting and C. Thies", booktitle = "Toulouse '90. Third International Workshop. Software Engineering and its Applications Proceedings", title = "Programming tools for the Suprenum supercomputer", pages_whole = "1029", pages = "951--963 (vol. 2)", month = dec, year = "1990", publisher = "EC2", address = "Nanterre, France", abstract = "Programming tools for the Suprenum supercomputer have been developed. The programming environment comprises a context-sensitive hybrid editor, an interactive interpreter and a literate programming system. The editor can be used as a text editor as well as a structure editor; both modes may be mixed freely. It guarantees immediate recognition of syntactic and semantic errors, but does not insist on immediate error correction. The interpreter can be used to execute and debug incomplete program fragments. The literate programming system offers documentation support in the style of WEB. The authors describe the main features of the tools and demonstrate how they support the construction and documentation of programs written in extended FORTRAN8x, the programming language for the massively parallel Suprenum machine. (7 Refs.)", acknowledgement = ack-nhfb, affiliation = "Tech. Univ., Damstadt, Praktische Inf., Germany", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110P (Parallel programming); C5440 (Multiprocessor systems and techniques); C6115 (Programming support); C6130 (Data handling techniques)", conf_date = "3--7 Dec. 1990", conf_location = "Toulouse, France", conf_sponsor = "CIGREF; SEE; Syntec-Informatique", keywords = "Suprenum supercomputer; Programming environment; Context-sensitive hybrid editor; Interactive interpreter; Literate programming system; Text editor; Structure editor; Semantic errors; Error correction; Debug; Documentation support; WEB; Extended FORTRAN8x; Massively parallel Suprenum machine", note = "2 vol.", thesaurus = "Parallel machines; Parallel programming; Program interpreters; Programming environments; Software tools; Text editing", } @Book{Spivak:LTW91, author = "Michael D. Spivak", title = "The {\LAMSTeX} Wizard's Manual", publisher = pub-TEXPLORATOR, address = pub-TEXPLORATOR:adr, year = "1991", } @Article{Thimbleby:CJ-29-3-201, author = "Harold Thimbleby", title = "Experiences of `Literate Programming' using {{\tt cweb}} (a variant of {Knuth}'s {\WEB{}})", journal = j-CJ, year = "1986", volume = "29", number = "3", pages = "201--211", month = jun, } @TechReport{Thimbleby:cwebman, author = "Harold W. Thimbleby", title = "Literate Programming in {C}", institution = "University of York", address = "Department of Computer Science, University of York, Heslington, York YO1 5DD, England", year = "1984", abstract = "{\bf Cweb} is a system of structured documentation based of Knuth's {\tt WEB}. The philosophy behind both {\bf cweb} and {\tt WEB} is that an experienced programmer, who wants to provide the best possible documentation of his or her software products, needs two things simultaneously: a language for formatting and a language for programming. When both are appropriately combined we obtain a system much more useful than either language separately. {\bf Cweb} combines {\bf C} source with ({\bf di}){\bf troff} (or {\bf nroff}) documentation (whereas {\tt WEB} operates with Pascal and \TeX). The full facilities of {\bf C} and {\bf troff} are available to the user.\par {\bf Cweb} operates effectively with existing Unix text and program development tools, such as {\bf make}, {\bf tbl}, {\bf eqn}. If speed is important, {\bf cweb} has a built-in formatter which is much faster (and less resource consuming) the {\bf troff} for drafting or using with a lineprinter.", } @Article{Tung:JSP-10-2-113, author = "{Sho-Huan} Tung", title = "A Structured Method for Literate Programming", journal = j-SP, year = "1989", volume = "10", number = "2", pages = "113--120", ISSN = "0935-1183", abstract = "In order to make computer programs easier to comprehend, the methods for program development and documentation need to be enhanced beyond their conventional treatment. Literate programming is an approach to programming that emphasizes improving the readability of computer programs. The paper describes a structured method for literate programming. HSD (Hierarchical Structured Document) is a tool that supports automatic code and document generation from a hierarchically structured document description. An example is given to illustrate the use of HSD. The ways in which empirical studies on programmers' behavior influenced the design of HSD and some directions for future research are addressed. (18 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Indiana Univ., Bloomington, IN, USA", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming)", CODEN = "STPGE", keywords = "Programmer behaviour; Literate programming; Program development; Documentation; Readability; HSD; Document description; Empirical studies", thesaurus = "Structured programming; System documentation", } @Article{vanAmmers:LPV90, author = "E. W. van Ammers", title = "Literate programming with {VAMP}", journal = "Informatie", volume = "32", number = "4", pages = "380--388", month = "", year = "1990", ISSN = "0019-9907", abstract = "VAMP is a method of documentation using a special relationship between man and computer. It was introduced in 1984 and since then experience has shown it to be superior to WEB. A block diagram of the program is given. (15 Refs.)", acknowledgement = ack-nhfb, affiliation = "Wageningen Univ., Netherlands", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110 (Systems analysis and programming); C6180 (User interfaces)", CODEN = "INFTC", keywords = "Literate programming; User interface; VAMP; Documentation", language = "Dutch", thesaurus = "Programming; User interfaces", } @InProceedings{vanAmmers:VTL92, author = "E. W. van Ammers and M. R. Kramer", booktitle = "{CompEuro} 1992 Proceedings: Computer Systems and Software Engineering, May 4--8, 1992, The Hague, The Netherlands", title = "{VAMP}: {A} tool for literate programming independent of programming language and formatter", pages_whole = "xviii + 717", pages = "371--376", month = may, year = "1992", publisher = pub-IEEE-CSP, address = pub-IEEE-CSP:adr, ISBN = "0-8186-2760-3", LCCN = "QA76.5.C6122 1992", abstract = "The authors have developed a module extractor called VAMP, that cooperates with a standard formatter. They describe the VAMP approach to literate programming. Literate programming identifies a method of documentation which explains to people what a computer is supposed to do. Generally, this means that refinement steps are documented in such a way that modules can be extracted from the documentation files. The tool has been in use since 1982. The experiences are predominantly positive, in spite of the overhead implicit in the methodology. The fact that VAMP is independent of both programming language and formatter distinguishes it from WEB and its derivatives. (15 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Comput. Sci., Agric. Univ. of Wageningen, Netherlands", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support)", conf_date = "4--8 May 1992", conf_location = "The Hague, Netherlands", conf_sponsor = "IEEE", editor = "Patrick Dewilde and Joos Vandewalle", keywords = "Explanation; Literate programming; Programming language; Formatter; VAMP; Documentation; Refinement steps; Overhead", thesaurus = "Programming environments; Software tools; System documentation", } @Article{VandenBosch:j-ACM-COMPREV-31-7-343, author = "P. N. Van den Bosch", title = "Weaving a Program: Literate Programming in {WEB}", journal = j-ACM-COMPREV, volume = "31", number = "7", year = "1990", pages = "343--344", acknowledgement = ack-eg, } @Article{VanWyk:CACM-33-3-361, author = "Christopher J. {Van Wyk}", title = "Literate Programming\emdash{}An Assessment", journal = j-CACM, year = "1990", volume = "33", number = "3", pages = "361, 365", month = mar, } @Article{Waite:SIGPLAN-28-2-21, author = "W. M. Waite", title = "An Executable Language Definition", journal = j-SIGPLAN, year = "1993", volume = "28", number = "2", pages = "21--40", month = feb, note = "This paper describes a subset of C, called C--, defined as a literate program using the Eli and FunnelWeb systems.", ISSN = "0362-1340", abstract = "This paper is an application of the literate programming paradigm to language definition. C-- is a scaled down version of C. The features selected illustrate basic problems for compiler designers: scanning, parsing, name analysis, overload resolution, static storage allocation and code generation. Features that merely increase the implementation effort without illustrating such techniques were excluded. This paper defines the structure and meaning of a C-- program. It has five sections, each dealing with one aspect of the language: basic symbols and comments, program structure, declarations, expressions and statements. (12 Refs.)", acknowledgement = ack-nhfb, affiliation = "Dept. of Electr. and Comput. Eng., Colorado Univ., Boulder, CO, USA", bibdate = "Sat Nov 12 21:22:15 1994", classification = "C6140D (High level languages); C6110B (Software engineering techniques)", CODEN = "SINOD", keywords = "Executable language definition; Literate programming paradigm; Compiler designers; C-- program; Program structure", thesaurus = "C language; Formal specification", } @TechReport{Williams:FUM92, author = "Ross Williams", title = "{FunnelWeb} User's Manual", institution = "University of Adelaide", year = "1992", type = "\verb|ftp.adelaide.edu.au| in \verb|/pub/compression| and \verb|/pub/funnelweb|", address = "Adelaide, South Australia, Australia", acknowledgement = ack-bc, bibdate = "Mon Oct 4 17:25:40 1993", } @Article{Wu:J-ACM-ADALET-9-5-84, author = "Y. C. Wu and Ted P. Baker", title = "A Source Code Documentation System for {Ada}", journal = j-ACM-ADALET, volume = "9", number = "5", year = "1989", pages = "84--88", acknowledgement = ack-eg, } @Article{Zeng:LPS91, author = "Yunfeng Zeng", title = "Literate programming system {CDS}", journal = "Journal of Computer Science and Technology [English Language Edition]", volume = "6", number = "3", pages = "263--270", month = jul, year = "1991", ISSN = "1000-9000", abstract = "The paper presents a broad outline and some implementation techniques of the literate programming system CDS. Compared with the previous ones (e.g. WEB, Cweb), CDS has two main characteristics: (1) a Chinese-English typesetting system developed to produce the documentation, making Chinese documentation possible; and (2) a suitable method for automatic formatting introduced to generate the software documentation automatically. This frees the programmer from typesetting details while still allowing programmer's interference. (7 Refs.)", acknowledgement = ack-nhfb, affiliation = "Inst. of Software, Acad. Sinica, Beijing, China", bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6115 (Programming support)", CODEN = "JCTEE", keywords = "CDS; Literate programming system; Chinese-English typesetting system; Automatic formatting; Software documentation", thesaurus = "Programming environments; Software tools; System documentation", } @Book{Broy:MPS91, title = "Methods of programming. Selected papers on the {CIP}-Project", pages = "xii + 268", month = "", year = "1991", publisher = pub-SV, address = pub-SV:adr, ISBN = "3-540-54576-X", LCCN = "QA76.6 .M4543 1991, QA267.A1 L43 no.544", abstract = "The following topics were dealt with: meta-models for system development including OOP; transformational programming; software reusability; formal specification; deductive program development; reverse Polish notation; literate programming; quantifier elimination; and algebraic and functional programming.", acknowledgement = ack-nhfb, bibdate = "Wed Aug 31 00:52:14 MDT 1994", classification = "C6110B (Software engineering techniques); C4240 (Programming and algorithm theory); C4210 (Formal logic)", editor = "M. Broy and M. Wirsing", keywords = "Meta-models; System development; OOP; Transformational programming; Software reusability; Formal specification; Deductive program development; Reverse Polish notation; Literate programming; Quantifier elimination; Functional programming", thesaurus = "Formal logic; Formal specification; Programming; Programming theory; Software reusability", } pretzel-2.0n-2/doc/bibliographies/index.html0000644000000000000000000000203606360651243017606 0ustar rootroot Index file for directory "pretzel/doc/bibliographies" of Pretzel distribution

Index file for directory "pretzel/doc/bibliographies" of Pretzel distribution

Files and directories are:

this directory

    some Bibliographies
litprog.bib
    version 1.55 of Nelson Beebe's Literate Programming Bibliography
prettyprinting.bib
    personal bibliography on prettyprinting
supplemental.bib
    supplemental bibliography for project report and PretzelBook

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 10:58:11 MESZ 1997 pretzel-2.0n-2/doc/bibliographies/supplemental.bib0000644000000000000000000001145706255210314021000 0ustar rootroot @article{C-comparison90, author = {N.N.}, title = {A comparison of program readability of C++ and C}, crossref = {}, journal = "University Computing", volume = 12, number = 3, month = sep, year = 1990, pages = {104--109}, note = {}, library = {not available}, annote = { } } @UNPUBLISHED{ Detig92, author = "Detig, Christine", title = {{\sc SoftBook.} {Methoden} f\"ur das literarische {Softwaremanagement}}, month = nov, year = 1992, note = "TH Darmstadt" } @BOOK{ Jensen85, author = "Jensen, K. and Wirth, N.", title = "{PASCAL} --- {User} Manual and Report", edition = "Third", publisher = "Springer", year = 1985 } @BOOK{ TeXbook, author = "Donald E. Knuth", title = "The \TeX{}book", volume = "A", series = "Computers and Typesetting", publisher = "Addison-Wesley", address = "Reading, Massachusetts", year = 1983, } @MISC{vanLeeuwen95, author = "van Leeuwen, Marc", title = "Differences between {CWEB} and {WEB} prettyprinting grammars", howpublished = "Posting in {\tt comp.programming.literate}", month = feb, year = 1995, note = "Correct subject header might be different." } @MISC{Ramsey:noweb:www, author = "Ramsey, Norman", title = "Noweb home page", howpublished = "WWW URL: http://www.cs.virginia.edu/~nr/noweb/intro.html", } @MISC{Ramsey:noweb:hacking, author = "Ramsey, Norman", title = "The Noweb Hacker's Guide", howpublished = "included in the noweb distribution, also available via the Noweb home page \cite{Ramsey:noweb:www}.", } @MISC{Ramsey96:noweb:filters, author = "Ramsey, Norman", title = "Re: Prettyprinting in noweb (was: the underscore dilema)", howpublished = "Posting in {\tt comp.programming.literate}", month = apr, year = 1996, } @MISC{vanLeeuwen96:pp:control, author = "van Leeuwen, Marc", title = "Alignment of assignments in {\CWEAVE}", howpublished = "Posting in {\tt comp.programming.literate}", month = mar, year = 1996, note = "Correct subject header might be different (date and number here: 2986, 19 Mar 1996." } @MISC{vanLeeuwen96:pp:noweb, author = "van Leeuwen, Marc", title = "Prettyprinting in noweb (was: the underscore dilema)", howpublished = "Posting in {\tt comp.programming.literate}", month = apr, year = 1996, } @MISC{vanLeeuwen95:pp:layout:style, author = "van Leeuwen, Marc", title = "On interpretation of layout features", howpublished = "Posting in {\tt comp.programming.literate}", month = Feb, year = 1995, note = "Correct subject was different.", } @MISC{klosowski96:cweb:pp, author = "Klosowski, Przemek", title = "Re: I want to produce PostScript output from CWEB", howpublished = "Posting in {\tt comp.programming.literate}", month = nov, year = 1996, } @MISC{neeracher96:lp:indexing, author = "Neeracher, Matthias", title = "Re: Simple LP experiment", howpublished = "Posting in {\tt comp.programming.literate}", month = apr, year = 1996, } @MISC{schwartz94:use:of:prettyprinting, author = "Schwartz, Barry", title = "When to use prettyprinting", howpublished = "Posting in {\tt comp.programming.literate}", month = oct, year = 1994, note = "Correct subject header might be different. Date here: 5 Oct 1994.", } @MISC{ramsey94:use:of:prettyprinting, author = "Ramsey, Norman", title = "When to use prettyprinting", howpublished = "Posting in {\tt comp.programming.literate}", month = oct, year = 1994, note = "Correct subject header might be different.", } @MISC{vanLeeuwen94:use:of:prettyprinting, author = "van Leeuwen, Marc", title = "When to use prettyprinting", howpublished = "Posting in {\tt comp.programming.literate}", month = oct, year = 1994, note = "Correct subject header might be different. Date here: 7 Oct 1994.", } @MISC{kientzle:use:of:prettyprinting, author = "Kientzle, Tim", title = "When to use prettyprinting", howpublished = "Posting in {\tt comp.programming.literate}", month = oct, year = 1994, note = "Correct subject header might be different. Date here: 6 Oct 1994.", } @MISC{dvorak95:cweb:nice:output, author = "Dvorak, Jan", title = "Re: {\CWEB} \& {\CPP} trouble with `const'", howpublished = "Posting in {\tt comp.programming.literate}", month = nov, year = 1995, } @MISC{pretzel:homepage, author = "G{\"a}rtner, Felix", title = "\pretzel{} home page", howpublished = "WWW URL: \verb+http://www.iti.informatik.th-darmstadt.de/~gaertner/pretzel+", } @MISC{Schrod:CWEB:LaTeX, author = "Schrod, Joachim", title = "LaTeX CWEB --- a bundle that allows you to use LaTeX as the documentation markup of your CWEB program", howpublished = "WWW URL: {\tt ftp://ftp.th-darmstadt.de/ pub/programming/literate-programming/ c.c++/cweb-sty-1.1.1.tar.gz}", date = "1995/11/21", } pretzel-2.0n-2/doc/bibliographies/prettyprinting.bib0000644000000000000000000005004205723110640021362 0ustar rootroot@string{ spe = "Software --- Practice {\it\&} Experience" } @string{ spln = "ACM SIGPLAN Notices" } @string{ CACM = "Communications of the ACM" } @article{Arab92, author = {Arab, M.} , title = {Enhancing program comprehension: formatting and documenting}, journal = spln, volume = 27, number = 2, month = feb, year = 1992, pages = {37--46}, note = {}, library = {}, annote = { The authors compare Peterson77 scheme of Pascal formatting with Crider78 and Leinbaught80. Then the authors develop their own scheme. They present a documentation scheme and briefly present two tools that do `interactive' prettyprinting and documenting. They don`t talk about details and methods used. lang = PASCAL cont = system, formatting rules } } @article{Bailes84, author = {Bailes, P. A. and Salvadori, A.}, title = {A semantically-based formatting discipline for {Pascal}}, journal = spe, volume = 14, number = 3, month = mar, year = 1984, pages = {235--251}, note = {}, library = {}, annote = { The authors give a new set of formatting rules for Pascal that are based on the semantics and stress vertical separation. They claim that they are strict and consistent. They stress the distinction between formatting policy (set of guidelines) and the formatting algorithm that implements the policy. Finally, they also give a chronological overview over published rules for Pascal. lang = PASCAL cont = formatting rules } } @article{Baldwin86, author = {Baldwin, R. R.}, title = {Systematic indentation in PL/I: minimizing the reduction in horizontal space}, journal = spln, volume = 21, number = 9, month = sep, year = 1986, pages = {22--26}, note = {}, library = {}, annote = { The author gives some traditional hints on how to minimize the reduction of horizontal space in PL/I programs. lang = PL/I cont = formatting rules } } @article{Bates81, author = {Bates, R. M.}, title = {A {Pascal} Prettyprinter With a Different Purpose}, journal = spln, volume = 16, number = 3, month = mar, year = 1981, pages = {10--17}, note = {}, library = {}, annote = { I've never seen so many typos in the biblioghaphy. A slow paper! lang = PASCAL cont = system, formatting rules } } @article{Blaschek89, author = {Blaschek, G. and Sametinger, J.}, title = {User-adaptable prettyprinting}, journal = spe, volume = 19, number = 7, month = jul, year = 1989, pages = {687--702}, note = {}, library = {}, annote = { Uses attribute grammar. Language dependent front end, independent back end. Uses (modified) folding algorithm from Oppen80. kopiert } } @article{Bond79, author = {Bond, R.}, title = {Another note on {Pascal} indentation}, journal = spln, volume = 14, number = 12, month = dec, year = 1979, pages = {47--49}, note = {}, library = {}, annote = { The quality of a formatting method should be measured in its simplicity. The author presents a very simple algorithm that implements a simple formatting method. lang = independent cont = algorithm, rules } } @article{ Clifton78, author = {Clifton, H. M.}, title = {A technique for making structured programs more readable}, journal = spln, volume = 13, number = 4, month = apr, year = 1978, pages = {58--63}, note = {}, library = {}, annote = { The author introduces connector lines as an additional way of visualizing nested structures. lang = PL/I cont = ? } } @article{ Conrow70, author = {Conrow, K. and Smith, R. G.}, title = {{NEATER2}: A {PL/I} source program reformatter}, journal = CACM, volume = 13, number = 11, month = nov, year = 1970, pages = {669--675}, note = {}, library = {}, annote = { The authors give no indication of the underlying algorithm. Input needs to be syntactically correct. Prettyprinter runs on keywords. lang = PL/I cont = system } } @article{Cooper85, author = {Cooper, B., Gallagher, B. and Sekercan, G.}, title = {Feedbacks to `A {Pascal} indentation philisophy'}, journal = "Computer Language", volume = 7, number = 12, month = dec, year = 1985, pages = {}, note = {}, library = {not available}, annote = { crossref to Heckert85, } } @article{Crider78, author = {Crider, J.}, title = {Structured formatting of {Pascal} programs}, journal = spln, volume = 13, number = 11, month = nov, year = 1978, pages = {15--22}, note = {}, library = {}, annote = { lang = PASCAL cont = formatting rules } } @techreport{Fritzson83, author = {Fritzson, P.}, title = {Adaptive prettyprinting of abstract syntax applied to {Ada} and {Pascal}}, month = {}, year = 1983, institution = {University of Link\"oping, Sweden}, address = {}, type = {Research Report}, number = {}, note = {}, library = {not available}, annote = { } } @article{Guillemette90, author = {Guillemette, R. A.}, title = {What readers mean by `good documentation'}, journal = "Information and Management", volume = 18, number = 2, month = feb, year = 1990, pages = {69--77}, note = {}, library = {not available}, annote = { } } @techreport{ Goldstein73, author = {Goldstein, I.}, title = {Prettyprinting, converting list to linear structure}, month = {}, year = 1973, institution = {M.I.T. Artificial Intelligence Laboratory, Cambridge, Mass.}, address = {}, type = {}, number = 279, note = {}, library = {not available}, annote = { } } @mastersthesis{Gordon, author = {Gordon, H.}, type = {M.Sc.~Thesis}, title = {Paragraphing computer programs}, month = {}, year = 1975, school = {University of Toronto, Toronto, Ontario, Canada}, address = {}, note = {}, library = {not available}, annote = { } } @article{Grogono79, author = {Grogono, P.}, title = {On Layout, Identifiers and Semicolons in {Pascal} Programs}, journal = spln, volume = 14, number = 4, month = apr, year = 1979, pages = {35--40}, note = {}, library = {}, annote = { mentions ecological aspect of prettyprinting: waste of paper when few characters are on one line. lang = PASCAL cont = formatting rules } } @article{Grogono89, author = {Grogono, P.}, title = {Comments, Assertions, and Pragmas}, journal = spln, volume = 24, number = 3, month = mar, year = 1989, pages = {79--84}, note = {}, library = {}, annote = { ``comments are second class citizens'' (p.80) argues that comments, assertions and pragmas should be treated as part of the language grammar. Proposes different views of canonical (full) sourcetext representation. } } @article{Gustafson79, author = {Gustafson, G. G.}, title = {Some practical experiences formatting {PASCAL} programs}, journal = spln, volume = 14, number = 9, month = sep, year = 1979, pages = {42--49}, note = {}, library = {}, annote = { syntesis of Peterson77 and Crider78 lang = PASCAL cont = formatting rules } } @article{ Hearn79, author = {Hearn, A. C. and Norman, A. C.}, title = {A one-pass prettyprinter}, journal = spln, volume = 14, number = 12, month = dec, year = 1979, pages = {50--58}, note = {}, library = {}, annote = { Idea of coroutines: printing and formatting. Printing selects possible break spaces and controls indentation, formatting decides when to break. lang = independent cont = formatting rules, system } } @article{Heckert85, author = {Heckert, R.}, title = {A {Pascal} indentation philosophy}, journal = "Computer Language", volume = {}, number = {}, month = sep, year = 1985, pages = {37--39}, note = {}, library = {not available}, annote = { } } @article{Horowitz86, author = {Horowitz, E. and Williamson, R. C.}, title = {SODOS: A Software Documentation Support Environment -- Its Definition}, journal = {IEEE Transactions on Software Engineering}, volume = "SE-12", number = 8, month = aug, year = 1986, pages = {849--859}, note = {}, library = {}, annote = { } } @article{ Hueras77, author = {Hueras, Jon and Ledgard, Henry}, title = {An Automatic Formatting Program for {PASCAL}}, journal = spln, volume = 12, number = 7, month = jul, year = 1977, pages = {82--84}, note = {}, library = {}, annote = { runs on keywords kopiert } } @article{Jackel80, author = {Jackel, M.}, title = {A formatting parser for {Pascal} programs}, journal = spln, volume = 15, number = "7--8", month = "July--August", year = 1980, pages = {58--63}, note = {}, library = {}, annote = { The author presents a parser for Pascal. The design concept is that a parser breaks up the text into tokens and editing (formatting) instructions and a final editor (formatter) puts the output into printable form. The actual implementation mixes both up again in that the line breaking is done by the (recursive descent) parser routines. The problems of formatting comments is noted and no bibliography is given! lang = PASCAL cont = system } } @article{Jokinen89, author = {Jokinen, M. O.}, title = {A language-independent pretty printer}, journal = spe, volume = 19, number = 9, month = sep, year = 1989, pages = {839--856}, note = {}, library = {}, annote = { kopiert } } @article{Kaelbling88, author = {Kaelbling, M. J.}, title = {Programming Languages Should {NOT} Have Comment Statements}, journal = spln, volume = 23, number = 10, month = oct, year = 1988, pages = {59--60}, note = {}, library = {}, annote = { comments should have a scope to show to which part of the program they belong. This makes them more readable. Scoped comments could be included into the language grammar. } } @article{Knuth-Plass81, author = {Knuth, D. E. and Plass, M. F.}, title = {Breaking Paragraphs into Lines}, journal = spe, volume = 11, number = {}, month = {}, year = 1981, pages = {1119--1184}, note = {}, library = {}, annote = { The authors present an algorithm that takes the global appearance of the paragraph into account when breaking lines. algorithm is also suitable for prettyprinting } } @article{Leavens84, author = {Leavens, G. T.}, title = {Prettyprinting styles for various languages}, journal = spln, volume = 19, number = 2, month = feb, year = 1984, pages = {75--79}, note = {}, library = {}, annote = { The author sees three different prettyprinting styles and presents a hypothesis for which type of language uses which type of style: 1. Languages with uniform small closing delimiters use the LISP style. ( key body ) 2. Languages with uniform but larger closing delimiters use PL/I style: keyw body end 3. Languages with several distinct closing keywords use Ada style: keyw body end keyw A special exception is C! } } @book{ Ledgard75, author = {Ledgard, Henry F.}, title = {Programming Proverbs}, edition = {}, series = {}, volume = {}, number = {}, publisher = {Hayden, Rochelle Park, New Jersey}, address = {}, year = 1975, isbn = {}, note = {}, library = {not available}, annote = { } } @article{ Ledgard77, author = {Ledgard, H. and Singer, A. and Hueras, J.}, title = {A Basis for Executing {PASCAL} Programmers}, journal = spln, volume = 12, number = 7, month = jul, year = 1977, pages = {101--105}, note = {}, library = {}, annote = { kopiert } } @article{Leinbaught80, author = {Leinbaught, D. W.}, title = {Indenting for the Compiler}, journal = spln, volume = 15, number = 5, month = may, year = 1980, pages = {41--48}, note = {}, library = {}, annote = { Formatting alone is a sufficient specification of a program's block structure. This is proved with PASCAL as an example. Compilers should also be able to ``see'' indentation so compound statements don't have to be bracketed anymore with begin/end. } } @article{Marca81, author = {Marca, D.}, title = {Some {Pascal} Style Guidelines}, journal = spln, volume = 16, number = 4, month = apr, year = 1981, pages = {70--80}, note = {}, library = {}, annote = { discussion of the term ``style''. proposal of a PASCAL style lang = PASCAL cont = rules } } @article{Mateti83a, author = {Mateti, P.}, title = {A specification scheme for indenting programs}, journal = spe, volume = 13, number = {}, month = {}, year = 1983, pages = {163--179}, note = {}, library = {}, annote = { crossref to Mateti83b lang = PASCAL cont = algorithm } } @article{Mateti83b, author = {Mateti, P. and Jaffar, J.}, title = {A correctness proof of an indenting program}, journal = spe, volume = 13, number = {}, month = {}, year = 1983, pages = {199--226}, note = {}, library = {}, annote = { } } @article{ McKeeman65, author = {McKeeman, William M.}, title = {Algorithm 268}, journal = CACM, volume = 8, number = {}, month = {}, year = 1965, pages = {667--668}, note = {}, library = {}, annote = { lang = ALGOL cont = algorithm } } @article{Miara83, author = {Miara, R. J. et al.}, title = {Program indentation and comprehensibility}, journal = CACM, volume = 26, number = 11, month = nov, year = 1983, pages = {861--867}, note = {}, library = {}, annote = { Gruendliche Untersuchung ueber den Wert unterschiedlicher Einrueckungstiefen. } } @article{Mohilner78, author = {Mohilner, Patricia R}, title = {Prettyprinting {PASCAL} Programs}, journal = spln, volume = 13, number = 7, month = jul, year = 1978, pages = {34--40}, note = {}, library = {}, annote = { kopiert } } @article{Morcos86, author = {Morcos-Chounet, E. and Conchon, A.}, title = {PPML: a general formalism to specify prettyprinting}, journal = "Information Processing", volume = 86, number = {}, month = {}, year = 1986, pages = {583--590}, note = {}, library = {not available}, annote = { } } @article{ALGOL-Report, author = {Naur, Peter and others}, title = {Report on the algorithmic language {Algol}~60}, journal = CACM, volume = 3, number = 5, month = may, year = 1960, pages = {299--314}, note = {}, library = {}, annote = { formatting standards are part of language description } } @article{Norris84, author = {Norris, D.}, title = {An {Ada} prettyprinter}, journal = "Journal of Pascal and Ada", volume = 3, number = 4, month = apr, year = 1984, pages = {29--48}, note = {}, library = {not available}, annote = { } } @article{OmanXX, author = {Oman, P., and Cook, C. R.}, title = {Typographic style is more than Cosmetic}, journal = {}, volume = {}, number = {}, month = {}, year = {}, pages = {}, note = {}, library = {}, annote = { } } @article{ Oppen80, author = {Oppen, Derek C.}, title = {Prettyprinting}, journal = "ACM Transactions on Programming Languages and System", volume = 2, number = 4, month = oct, year = 1980, pages = {465--483}, note = {}, library = {}, annote = { kopiert } } @article{ Peterson77, author = {Peterson, James L.}, title = {On the Formatting of {Pascal} Programs}, journal = spln, volume = 12, number = 12, month = dec, year = 1977, pages = {83--86}, note = {}, library = {}, annote = { kopiert } } @article{ Ramsdell79, author = {Ramsdell, J.}, title = {Prettyprinting structured programs with connector lines}, journal = spln, volume = 14, number = 9, month = sep, year = 1979, pages = {74--75}, note = {}, library = {}, annote = { uses semicolons as connector lines in the source code crossref to Clifton78 } } @article{ Richard77, author = {Richard, Frederic and Ledgard, Henry F.}, title = {A Reminder for Language Designers}, journal = spln, volume = 12, number = 12, month = dec, year = 1977, pages = {73--83}, note = {}, library = {}, annote = { - readability more important than writability - classification of comment types (p. 81) - no language to date has desired documentation features } } @article{Rorbillard89, author = {Rorbillard, P. N.}, title = {Automating Comments}, journal = spln, volume = 24, number = 5, month = apr, year = 1989, pages = {66--70}, note = {}, library = {}, annote = { distinguishes between narrative comments (what) and operational comments (how). Operational comments can hide statements and act as refinements. lang = ? cont = system } } @article{Rose81, author = {Rose, G. A. and Welsh, J}, title = {Formatted Programming Languages}, journal = spe, volume = 11, number = {}, month = {}, year = 1981, pages = {651--669}, note = {}, library = {}, annote = { kopiert } } @article{Rubin83, author = {Rubin, Lisa F.}, title = {Syntax-Directed Pretty Printing --- A First Step Towards a Syntax-Directed Editor}, journal = "IEEE Transactions on Software Engineering", volume = "SE-9", number = 2, month = mar, year = 1983, pages = {119--127}, note = {}, library = {}, annote = { kopiert } } @article{ Sale78, author = {Sale, A. H. J.}, title = {Stylistics in languages with compound statements}, journal = "Australian Computer Journal", volume = 10, number = 2, month = may, year = 1978, pages = {58--59}, note = {}, library = {}, annote = { kopiert } } @article{ Sankar89, author = {Sankar, S.}, title = {APE --- a set of \TeX{} macros to format Ada programs}, journal = "Ada Letters", volume = 9, number = 7, month = "November/December", year = 1989, pages = {114--128}, note = {}, library = {not available}, annote = { } } @article{Scowen71, author = {Scowen, R. and Allin, D. and Hillman, A. L. and Shimell, M.}, title = {{SOAP} -- {A} program which documents and edits {Algol}60 programs}, journal = "The Computer Journal", volume = 14, number = 2, month = {}, year = 1971, pages = {133--135}, note = {}, library = {}, annote = { } } @article{ Stylebibliography, author = {Thomas, E. J. and Oman, P. W.}, title = {A Bibliography of Programming Style}, journal = spln, volume = 25, number = 2, month = feb, year = 1990, pages = {7--16}, note = {}, library = {}, annote = { kopiert } } @article{ Waters83, author = {Waters, R.}, title = {User Format Control in a {LISP} Prettyprinter}, journal = "ACM Transactions on Programming Languages and Systems", volume = 5, number = 4, month = oct, year = 1983, pages = {513--531}, note = {}, library = {}, annote = { Gives a detailed description of a prettyprinting algorithm that may be applied to other languages too. Refers to Hearn79 and Oppen80. lang = LISP/independent cont = algorithm } } @article{Waters92, author = {Waters, R.C.}, title = {Using the new common {LISP} pretty printer}, journal = "Lisp and Symbolic Computation", volume = "V", number = 2, month = "April--June", year = 1992, pages = {27--34}, note = {}, library = {not available}, annote = { } } @article{Winter89, author = {Winter, K. and Cook, C.}, title = {A prototype intelligent prettyprinter for {Pascal}}, journal = spln, volume = 24, number = 9, month = sep, year = 1989, pages = {116--125}, note = {}, library = {}, annote = { The authors describe a prettyprinter that learns the formatting style from a sample piece of code. The prettyprinter analyses the sample code and captures the way whitespace is used after keywords. Such whitespace tokens have two associated values: (1) the number of newlines to be inserted and (2) an integer value that specifies the change of indentation. Problems: absolute alignment (of comments for example). lang = PASCAL cont = algorithm } } @article{ Woodman86, author = {Woodman, M.}, title = {Formatted Syntaxes and {Modula-2}}, journal = spe, volume = 16, number = 7, month = jul, year = 1986, pages = {605--626}, note = {}, library = {}, annote = { kopiert crossref to Rose81 } } @article{Yehudai80, author = {Yehudai, A.}, title = {Automatic indentation versus program formatting}, journal = spln, volume = 15, number = 10, month = {}, year = 1980, pages = {85--87}, note = {}, library = {}, annote = { prettyprinters should allow fine tuning the output with format commands inserted into the code (as comments) by the user. } } pretzel-2.0n-2/doc/project.report/0000755000000000000000000000000010765024777015617 5ustar rootrootpretzel-2.0n-2/doc/project.report/manual.dvi.gz0000644000000000000000000005164406236103327020214 0ustar rootroot‹׆x2manual.dviì[ tÕu^í®lc ˜Ó€ÁµÙAÞh%¶á@„ü#¥Ø–±Ä_]Êh÷íîD³3ëù‘´„Ä9Ä4‡m4ØVËð¡!1¦Më4ÔN)9=2$…¸¥=$phÚЊ$œ€Qï½ï½ÙÙ•èñiOšªslË;3ï½û÷ÝïÞ;û‹hÃƾ}Áåø‰½ºxi/»a©áØÇ^š\³æÒD²5Ñž\›lkmý£È þLÃÏžèS‘ÈÈžã‘Èžh}¯µó‹#c‘ý>>µqݳÿfG>òRWäÌû#©¼™¼ìõÛ{LfßÊ´¦ÒÞ%ðÀXäû±ìm¥ûGܯëØd˜¬<÷ö§íœ¢{ЇwÚåéï+LU÷lf–*-ôÌ7¸kªõ†¯m=5²N‚hù¶ÙàN7^Ç4uؽö•;Ý_.+¦­Ã“{O§'ÿré²Þ.¼¸N1ó–­¤mØ{,òµ·v/ß’²þÑm%f–áz{²ÅCÕ¬(íi¸êñâˆ{é¡}Ss÷?n)FæÃ~óåž­½9Õ*Çö½—WôÝ^vÍ3t­è¥ Ðg¦åÙ9æáoEoiÙô«¥ºgd<¡‹„Û8üD§¡[ŽfÓíâó•¥ È6â6Ú×ÏÆ Ï(Çúú2†IwiŠÍpAØuÆ’^ÚÝxaÊÉ3Ý·.&J¥Ò]h݆4ðÇgZ÷øsâ8S]Oݼ‡Œ‹ÚŸ“Ê÷'Û^ï!ÊÓ«f30—Uª\iá÷ôüÿlº.п¿õéd ÔúH·>ºm£[§žud¬aQ›×V*íEùQ÷L$p÷¦C_ߢ›¨†m†c¦˜…Bwë “<‰éƽ ODw¾ —ç^üÇû€ü6â.:v&èæ~®˜d¢ôr}nôÀËE³½ Bì*7ú‡öÁVƯD¹í!å¶“r;;g˜näžyÿ¯Îÿ<|®ÄާÛ%ú,UϺ±ô „ŒXØ´vU`ª‰6½9†ðP”b;„‰îܯžña6©V( ôúBåMuëÀ¼ ªÆ,·a¸çìª:¥]R£´¶°Ò62`ˆÓœ®ÜÌÙ yk_0’ÕÑ)­Zík~}j ‹Ó&‡„JYCùEØ"G>ÿÁöRÎe!;·Õdžq©´u¯o @ºšƒêíXíÌ¢‰¯: jb£©äóŠIzͬ;9Õ@"¯®¹Dî4òÀ ÁÒ¶…¢+zÚëDbfnÃø“'§°ÿCõ¬ 'E›”9ÒK=øq†>¤Ú¹ ù6®žrêkÄ]xla²5äíºuxª2õRÔ9«7žœ¢þêÆ¤CG·X?¬ä ZPåzÛ˜…Õ«ÛpUÛÉ®¶ÙDçH²Žõ;Ù¬ˆYãϤ NÝX¾å×§ .E²FŠUÜ€éAwzÇa¨uÛK¹  ¦,76ò§'»õþ÷:k ä*IáìhõåJ-±…3Õs×Ê·Ï z"sSù”•J¶¾ÞÓãN/(VJÑ&V¸±þÉ“]­5ª!wZõáåV¨ŠöU|ðÉʼªFfމTÒK<|ßBŠ™n|áó¿©²sé ªzˆ7+ºõ4kè¸ùÝ$èR…w¹Ÿcx")°Ñë¿FçÍÒ€}F6`û¨{Îßì¨iÀöuæ”jlîáùÉR¥MÜýzW·îb_Ö4ÜÈáù¢ËZª¬×'f&£rìÎ3¡´¨Éê¥8éõTËS¼LKc˜cd®4ë‡=|ÌX0,z-,OåWò.n’‡õ]µ½"úxÂóü·{žn>•™ØF÷ñN؃­”¢))f•ã±ï¡NL%ÅG&Sà¬Í  U,(,¤P;È›É@DOIÚ±lúÍÓÙg1,úåú~Dhš”ÿ1y6ˆ°lé¡sÚ7O^zh_‡íºc$gÊÀx´ë)<¶2¢‘ò†e×Jºò‡<ÅâÛ(?¨ „n¶ýÓØ°Ú¯±7ú¹j‚%È ,ÒCJU4qTÜ 4VŽ;KÀ.Õƒs™qE|(í !þjÂ'ªÁ;TÓË:¶EšÒ ÜÊRµ¢4.¬ŸSô¬G#%ǯeø]ÊË•£w?C^:ðÂÇ‹9ØÏʰñR|«GÉ5ýÂI>iÃÇc‹]•rüŒû³ê O‚ìï(YˆAE÷úwƒ<«àƒ€dbOé玀׸•4ÏR󪹃‹,#öÈòÌRŽŠ0š!áBh1œ[´¿3Œ“-/¯ øè¾Þ7Ëh©îk%©èdŽ ¨P#ØWJäØŽg€Òh`­òMÓÈ{–“‚msÁñ=iß)åX wÞª£ÁÀØÐ>æçä)b‡ëÁAË±Óæ‰Ñ‡W„• 't²©eÇ#ÍkÃ([M¶NÌòôg›áÐtfη¦ `S Ž+N,G™áÿèWõòµ¸±ÅŸK}Ã'ÇߺOµWœ=Ê©à2+ ”Xub?¥)–Ŭ6,îÜ—Ž\ç†Mg *=€}•cƒO1Êå6=€1¸Y±lr´Pd _ê ‡›Õ-½^ rühó:"n[Ù&˜®ñ)ð§„*ÌÛ^@w43,e7yA,6>U»#€,3mE ¹òmy–Gíǃ„äÁ€*Ç—ÏÜW!!¿Ð6zÍïp|jèŠÆ¥ƒ4rìùŽ ¨ÅßmoŸÀ“)4¯4L«Љë,ЙôHš‘Ù ¬bS9¾g”²¼J1)o‰T¿ƒéÓ Î®Ñ˜ÒªŒ'Økê&È UÊà Ã@58Ù÷oF­#xœô '󹪛J•s¾ÕA·Ò9zûƒªÅ!@ _(ó¸ÃâøÅwuÛ˜¹|Ôª…‚ƒ_Àñu 08}0 K³4CÈ—€iª6+G» á.+W}~DLJ[pO:@±&©FDŸ÷ÀÛ ,.®+ð—±™j—cG.Ih= ]Š 4%à 3Ç‘Kò ìæ§9j÷ÓÞxs6à†u(ßÏàŸ8½:õÆ¬Žˆ‘g Ü YüÐdL/ÀgBú$ec ¿pÅP¢†­è è&'D§Æ;cßø':&æ}J×€¶ÜÙuð¢ù‚ƒN @k`¾*Ð ÓN¸Þ–͹8ΰa ±…Év8 ;]ŽÝü$Ü®¡úŒO$<ê/mø$#fyngêØƒ´$x¥ÕŸ†ˆ‰”ßBÂø%©ZU†€°Kƒù–Ì»‘ §½i¤-“ÜÕË(FTŠà…ŽQ-9&‚cȘ¶s¿CáóU&¦Ê«¶J¦I6QI»-#`9 º%ͱ²b ëDLr ¬—¢O_œ14’,ñMŸ³_ˆY+”àD.¡x®FÔºoBD‘e×Qtq|ƒZ|ÌTÙÐxô½NÃãœèHŠO‡¥úB±ÝÄu"i¬Š#Pª0ˆ‹‡ÁâIO·f ìªÞ|æN8ò]íö(‡Ò:A‚ô]Bò*¨²iéAÁÙ•Q2L¼ð–\!…X%:ê\²`¡ÿf+Â6l˜¥‰‘Çi¡x%ˆ6û~Ï A;>ØXÁlÀèÐÁcßÜ‚¾êWøc i9éSñ1®4f3Ð1µU¤‘2¼ -…™±m ^—|-¥XLbiö"‘X (Ôt_¥ÊÒßß; ®+¨à:=“ \¯Ðõš‡Îào¥4f2³¿•Rª,ze1/µÐqãñ?§@Za±[‡]@¸@ßH¾tè·qjxj{¿  C·S!X(QÁ¿hl{6Ö˜Þv€›ãø0K7‰ÓYŒøV9ö¨LôSýèµ+†kˆ·l}æÚõë6­wc~jb¯†HùXÒŠZàaçkT‚ÀÞØãšý`kM“òÊJC'åЋqÄTQÚÀ¨'³ýÃËÎ|’{ä+4ì‡ð¾>7z×dÑ…ø®¾\Šén`o¼@ÚAç ¾Š ßCWÂr9PÝœ*˜³®ä‘>Ë¥Æç¬þƒÍxÙY‡ø"*ò¥e>o¯óL,Ìa²´[Æc›u»±MÉ) ð¦ó-Qœ“7(çÑÁ‘¨“ Lþ乸 ²ƒ9[|"¯î4ÀB†Œ\Ö¾Uæ\Ž=rözä'9Ì,º§¦™²ÌmüÌÁÞª—ˆSƒôÂï 3 YµÔPþÉf,éaÅãªLÈú›ÈÄVèíÏOÕõÑk8¢Nó¸=£ôû˜éˆŽì&:µ –nòºÝx³–KI™†{t}`8ÔwþÑ R½¸–+ñJ( ˆt ÛMcYW5( lÔxÞŸ©¿‰ÒC?µ“?ñ÷ÉBÄ?(ÇÖýc•— >)hñ…Vßfžæo³Bú׺º3AH(X²W-P5Ù¤5a% <Ž)ß¡ × ä ó=¤~cm©r.áòð¾‰gàn–βOšýÙDðÄ@ÂέLË·hiV*‰ ?± ð±ìÓ߬éd¶…;™ü=°Sz?#úu]LäQÑ[~J®(Å'V™Õ,¾…ä‰Ñ;€”n^Ãja”®B=0Žø[ϑȺ÷­çf©t%—¦¾Mý¶À¼OéY·|óÕkñ鞀¼MwRA©:™7ÜéÏ6ãɬ pÔ…ë†]޾÷¢Äýe+ÜxïÏ )É9V­ºRÒ—…dðÖ1<´—ÞJœôƒ}f/Y´mc@íÒàË¡7 Ž€ë TSWV3€¢ l’¥÷» ì°!1 à;JH¨1'ˆÓ’þy î©mhbÚl°ÑëP\õDOŒVåôA¥f:ভ»9{”Eø=zæ£*é-Ç6œ'ÝN­’Œäp 7åMAÚ›Ÿ-å˜z¸+9£Î…€LPåêf&lwÇ.ÑÇæÄ8ÈsT½ÏV@ܱ«>åy ¢IZ­µû,“SªTSc›`¾Èg!/Î|ݲžón8–šqÊ>¨Zà™ê­$¿· ëžãkvîÜ ·üÕDc¨±”ZâA€–£oNb£föŽÅÔüS÷ô_¦"y5Ùú·!õeŒ¬ø+=õäi¦}`—Œx§/°†l³áj“–Z`ͺÇñ¦`¨â§in"N nè€HùXeQ#+ecØÖ-²2`úÙrlô„° Aåë"%ÐWD^À¦ƒS(`iÇûÒA±³ Ǥ°âÍ\ 0‘”ã µ¬H¸óöìe¿Ä½ƒÇe+»nÄrð8& LÞKHòv:K·¸çe$<ÑaÅŽôD96ç<Ü.m_ ú\ðJ;P(‚4œ’%ÞY-Sõ½¬ª´kI…$Ç*ú]9¶ëKm‰6ê3¢Ã\*[øV¸ ÅÁT'1‹Îcij6çcñLl„|ˆÙélo€BäØåè=óBK d“ö¨ùîo™=:es 1’Ë¥½È ïý ©h»¸AN>WíÚ£{HìÁ’'B¯÷tŽT¦#‘‰‹/.¹ç4¼Ï˜BF@𦊒cZš¦!m6Á¸f­-í=)Ÿ“žÆ†K%÷Ê[·Ntà=[¶ußš'Sjm«¦–¸WDG ¸%šM,tµjA–Ü®I}¢Ã9ßK•cιÔêé‡ÖpãÏ~¢W|9‡º|Vzi »å¥=‘ÑAw¤òÃÓ׌ÐOåê«Pò>~öm²ô(•àã±ÈÃ?9·òÓƒîŒD2,ÒñìDeaÇ_ìŠÀßøÉHå?úhÉí˜ójðQé¾ î¦UÆ"‡_YRymÛ¼]‘yK_ {à³ïžßƒŸM5ìü×-VáKSu–lÝwU ï¹»ò…ÊÛëï„Úwr×q‰Üwïî©hÍCsñ¡¡dë#+é©?%Z}jѾ·åS+…HñøXeòŽv~È;Ï*Òò½[g î‰tø¼ŸíŠÌ?z[X$øŒ?Rù«?9>{°å÷&x¤£Û„iÝôöïà7ËVÔ1¿þË»Ÿqw>5‡” ÛüÓ7o_22ÖÐphjùfkXøÀ›6¿*KÑGÇ"_þãÅúú ­uã;£·ÌLb‰RÍœ• Á'Fƒ[ÔÙòà[cË£o[÷æ^ϵë{oZÍXd²ï‰KêŸ<´ß6ð Mí5‘|ÖËnMtñ,9ý¬Î"mÛÇG^ï6<`W[6Ãg6ûKMÃlg৆Aw@MŽ"•ÏR±CiTy3®WŽ­08ó õnÑOrÌõ—cyÀ©L}m°"Ôо´äý]ÊÙ—ñe6â/P—Y',jx_µÓõXDp„¡CàG“T¿ù¥ïö¾Ïˆê±ˆPÚ€;SµGç 5¢âËœ ¨Ia<ÉÒÅà]Ý€Êó;Ú|5F§84Qbð;fþ .•£ ™ìqaM+ÇYmòò™ø~ñ"Jð£Uõ´:¨¦ÙnßOéb4ÊŒ]ÚJã<|„f„4Ýãcä€c“ÜåøýŠ8*!èA€ºÔfð2àà¦!†#&<˜¨¶êÑ/Á°ß¹&§ðÂÈæiÖrѵ$%„ê8Åãû54ï°s-nüh›Å˜/z‘>}gÇ7hh#…©{Ó@LhÉ8<†ð“P+K~ƒGÔUA¹Œ+J•Å÷íìKhX ¿œ,†/Šo\õLÓô*þùHè6ÃNoµZŠþÝg6²°X¢/[N¿ìÁcÝNÖ¶þ‹³k®ª¼ò—ܬˆÓ±:[lI DZix¨Q+AP£ääæ$9pñž{ )P°2ûHÊáŒ×SR V‡Š#¢Dz¬KpªÅÖh–«SµSŸ•™qù¤Tk+Î~|¯sî²ü‡Å=Ïï|ßþöã·{'[9è‰0¸’*³E¢áÃnæÌ2^¸ñJÌæ[n:Hx:…DøßØŒC`" ½¬ªÛÛö¬•L°µŸŠ8±bM-ñp°ÝjÞT<‘غµ¯ˆø.^íY¬ØCd¦L»rì%XQŒü@„Ð2 ƒÚuªŠ5Ò˜Qwó†IÁ¯bÒHlsp«¹]*|0¹µM€!9\PBò+…ávFûPÆÊK\ù°´àZJ á„ÆvpÇ , }VÞÕ ¿± ‰ãcùnÔÕš^†hÇìþA6äQƒCþÛf ‹€¶Ú|Ï,¸®WgKl{Çm¢èýÁ*ÄîÆŽ%¤IHÂ4ò™rA’ÀqÑÐúHµË¸'P 4®_‹P1BÎ{ŒEüö,äõˆ¾> Gì|²QÖŠ_`;ô¥+~$>`˹áØ*? Œ›%R/GÃ*ÆÇï²äw£ÃБ³mõ6z²Ö6¾OäÇcZùÁv4WSÄ“yÎ`l½¦{€þJ|Š]#Š3;SÙ6 \µè÷‹’Ùfx>JR1‘0HåŠMª˜œü2± ™vÕOtÏÝMøm ûW»rbÄZ@15TÝí”ñ[ƒGœø4„Íä‹2dbù)'Ÿ§ãn E{½W]{¬s’2¶íÙ€Ãb-ke_ÕÞyJz`†¿–jÊ€Ö±È!‰$´t=”6§ÿ¡‹†®€Ê²¢9u䯂mâd$dÙèU]üü”bÕ%_K9ô¿¥ÌžãÇÕÐ×ÊS¤ODÜQ~$ÄÞyÚèU mbêiÏɉ'S¬ºåN|©Ëám ÏÂã¦É‚Ÿ Š¤ß ŽyÀL°ŠiF¥PW¥,Ẁœ¹è)©ÂôºÌZ&rKi)«þÍÈo…1YW.£AX‡P7,¶¬Èb¶ÙÇR;otïÞKíüD‰:¡x J0¨/=Ò‘Ðè¤ôÃÈœ°7¢­t ¾y5’“0)Ö`Xæ—D¯¶ÁQÞùö˜±sàüÞ‘—bòÁ†•^ .ÂmM"ç—3ü†ÛšhL@\Êew4bP$çI\BNáj*©¡µ ´°ä’T%1é+¨Hp“Ú¹\ ÄÊfá|‘gÛXue¤!"y›ªsâÞk>Õñ»´™¶Úí†êÉ7‡ìœBÝÌï÷»@šÍN 5×¥i´ º)Æ»s¬ŒqT .Š}ššX¬¶9™®<’’”Y│u¾ôWµZtÔF9J ÀÕuÕ3ÔÀRÓ&eÉ“LZé$RÞ9KÏ‘á¶l™ÛбCh£¥gèÓLÑDj#ÅlCWɾ0#Ì[dÐh‚]W$°¥ÃÂæ3›2Ž!ð –1úè°Œ™ÝŸ ˘¡°Œ#ùG§XÛ–Qã?5Ø?ýÿ6ÅN¿1/À£Q§×ÅðƒG|É}©6ÅNn»Å¼ŽW¼ÿâ›bµw\n^ÇèŠíÏ»â;xaâª_”:e Þ²e0áýý|A×Âóè‚;?¢µÀ³¢€q¦bó<ìùKæOžŒg…Ã-N?4¿OêþÇr±àKèôŒ7*[4€%Á×ñ’ ÿzþPwÎ#Ò2cøø?'JGw^zº8:¾|ÌÌcðؘm——”ô‹ËœrO}á±nÉòáïëÄž|ùׇF?ïo_;qDÌó&Ó¹™÷¡7£ÞèÖ⵿Œ÷ã†z6”Wußã]T›À—ÐblÿøšÌCÑõ¢ƒbMcÁºýÛ?n=óêM±q'Ï a°û=:8×nì¦ÆŸ•äŽìW7Geï5d†.¹¿æÇæè8f\ñÚÁ_ëÈKþxêß6Áö؆ç0^:ôÔžÜÂc?o9åñ§U'>pA€Õb¦þéÞ†~óªŽÜ>0æÜ áU«®ˆ}¸}JøÀ{Ï$ÂÞ8î…ðWKá/ô|7zà&y`Ý÷w›o¼ü¡ÐïàÈ„~os™¿·Ä¶›:¸­pÇÝã§ï ]ÿ›]+C¿ŸxuFè÷£§úýÐe¯…~ß¿éç¡ßw?¸%ôûŽwùA¼«c›v¿]’ ¾â¶ŽÝðàÖãí5#lêØ -yS{½ï;Òž–»66`{#îZœà¡lèÔ„ûwÁ©º9ý;ÿah¥0H•ÿÉ[ŽJo»]й—“ñ0s(1c1¡*p9ȵTcœ:ßÖÏÕˆ!ñX·}±œÇšïÊe àß[Aê…qÛV: @)°ÓÝêóN¬_ùè™_n-eŠSGL ˆy],ý`|wâÖO~7ûbŸüò“&/‰L뜉ûÍ—7xŸkƒ+Ázh1që~â¡ ‡"Õ[N`ñíï…ðžpɱózáG8'††t^;å 8c·Ã\V(d+ÆW¼éf£îõ‘eçVMéì’ #¹¾ë?Çg²y[çTLÎf¬ld«ì5Õw0Z¡Ù<1ñ–= ò4cËÍ *Nž²+˜‘IüËËMAï͈:P=cw žš®à,$(N¼EStâ}|ó@âý©=>¦|‚.2zôŠ›)ƒ™Æ6D„¦Ò!©Ìûˆ¯ª÷ªWî€qq¥8 “K‘V+qÈvÚÌt}Æ›± ^,GÛ^õáDSÅ H€|i´=•“)p]žb¼÷xvBd$­rqÊȉ ÞðWÉndΟ–Åé çŠ$S¸<@f®²i3ç@ãÓ%¥Ä¢ËSC–Hº!ž¬–iõJÀD²Zƒg„‡©ï6jŽYÇuÏù àã*C“ Wõ@}» 6/g—‰*ÑWT¼>>¢ 0å ªwqE¦… [˜0ÊR†D døž‡àD&àñq™Uçý rªÌfà %ëÿ:ÄM’[]8·bYú*0Öb|âÑž_•m«ˆO}Ë,ù®,/€Ag£®¿ƒ›lð0ÍcÎ[´l+™íÿ“Ë1G¹\ôÕOƒ\FßuWry2—.Í,¯—±ÛX¹ïöK·)TKÜ]ÈñR7vÊïš±¸Ñ14îþ’/Š^1±­Ä«A;ׂÌ_Œ|Ót‡TmÈÁÇ©6„ QYU¨™qrìäE†2¯(+*¾QUáЪ!ÅafrX/ðŽìè©¢Ag½Œ~ êñ=¨¸À¶¡ö²`*ò öˆy¡ä“ލ¶Äˆ 誩o.« ”’qË\âý^DDß NQ9L¬áFRò+°ÔUF‹&S½‚®(3òL]$yЉþ„NCm…/\Í > žÁ|lFÉF2Cfµh4#uÐr¢d ÄŸ(Í88¨¶ðIå·ƒ;âc]¤ÛÆ(”œíUVéÜG>uÏ?ÐöWÝQ™Îàïy Ú67¿ Ñ-üÝ¿u¸¡#_š(to¹»i8˂ۃwtV¸#”n·ü|•z˜Nÿ_0pä¥X¸ïÑö˜è{åìj i«ô€Í:p?…äœ>Å„” ËÕ…ÍB•žd2²#MßRÜÕã“|+L_ò© Œä´óT¯=sÊGÎ/c°‡,åßðKŒ™[þP>Ç^±›¢]\2qpÅÃH¡K@ G!ß•C,pÞù÷´±û=Ôn£oަÈgªö!Â3Ã&H}îGdÈ?¨gL6ôÍÎ,"a¸¯Ï$}ºüÉA ƒC xAáSÄZdšÍ#³¯D>VA T[Â¥*PZL)›²˜ÜöZr%Áû¥$µ£D[ÊDÔz‰e ]¹îÌr}–…m#!»v‰à’ÚedÅ`ÛsVb¥¦„çÅ…°…¼ØÄ©§F9"œúf,Ê<×/Šè]Á ô@]ž˜1 –(:Ë`°Äˆ\.¸—JRrÈ ±É"/I;¢h¥¼äº˜Ìñ@Im¨"2Åxr¹P!ìb€Vj6\ý„ÞÚ%EXù²[’¡*AQ·5»é‰mÔ[¬„}Õ@-S•ŸÕÎQ‘“víT‡Ÿ¶hVÊÍ2=W¶@ÃW]¨„¨Ö è¼o íå$j£I“´ü6#=­àʘüsG“_¹û³Ñ ΋ÄäÓæî®éÈfk¼3÷½1¯q‰ˆœá°yÔ;uî»k‹Õs?š4É_ãé<„KO’Ó ð8Û*(#l ôb züÈi–Í3P7]ÖáuBo³È*½ƒ9^bgŒ™ep•2¸àœn% -1ÕÚÝ*&ºæv ¥LZ:ôdð‡©A›5`)xuaee{#ñ±sÀBå'djÑo±*!óÎ ¸Âíu°bw¾ÔXQéšljìïPŒ¯ê‘“ƒ¾CŠ\&Ø+÷5\²!«zHµ¤±å£ÖÒ˜•@χËF$æ^åÏ䬠HÑÄdØ!ÓcÄ懫-ŠíÑdç±ç[/_;Š¡Mµ»64?¢¬ØeA)á–š´:ÝYû¯†ÉÊêÄŒì÷*›I¦°sÎxÝlü£/B쯞:eÖ5Þ¬}/.hº°©¹ÿ6!Ökk¼sŸ_´xáexŽ¥º¥em?™¹©yøh/ØÇëå=W[S¾y þƒOœäÙðaÓ|ß¼¶¥ÅÉûx?ìžÉ~Íú}gĬj¼ñÞZ'·Vw.›´Û 9»¦;kñ’EóWbGšE>=±Íé\É# Gêa´ä[<8ß’¹Æ«ûøäÓD¢‡ƒüew3jÊñ¤rg”üólDªT„Ë*,fC×Ê´Ekíyö *xÒ—Á@PÌn÷R6˜nBwj¶2Ö‚Ê;½™nçК4 ȡʕàˆÊ~ %h@¡Ô3¹|í¹ýƒãŽÌ00“]“è˜$ˆIøÚ8-¨Œª7€Á«TT^±KËÊ­©äû§‰'hüýãxÏYa3Tzùì,æwãÇ#Sš,S¸šÍ╊ÒÇTÓò¦¼ÉÊF©à¼–ÕÞÎõp#¹É¸ O{¶Z:|PÄiÙÔÕ½^CQÿ¿Tž?‘éAPŠûŸˆÂ<‚6êl⿤…tD6Ä•œ]ò?tèo4Gçt2œÄ,>ÿ µ°í76Ú@ÕÏ_—½¯Ž#+‡Òh{…OÆT55hkð¦?žN#lɦͦN¯áï>Yrßaújq›Õ©RUOâ ð€âK\Lý“”Spo;ytq°3ÒççÙ˜ûé ¤gš’h:DÉyA36ÕI=èl du&±7fJKvµXcš±õ´ß„f5qI77VÉK%Ù롱!¾XLAHÞ%‹Vô£Ô¨‹Ó¹( ‰…<àŽ¨tnåà§Áíü Ñ‹ôE²qèyÈ6¹*GH.ñã¿"-?°±`éÙ2ˆ~Þú#îÉ”jŸl‹€1\¹’[hg¸¦êÏ_§ëܶ*Š=í.otóè2Ë1Úœ2&µíÚi‡ÞKWÁ§>ÜFûóÉÚ­W[×ÄZp1 Åý?°ø€(]2ÏHA½ØV종$W£ÝšíÏ[xaÓeà©§ó+ G^xÙa¤æHÿ÷Ø£óùŸÍÿñUÓ2íˆã óŒ`o^Ÿ—[¸˜R’†«¨‰âe’c´'—¡~Ý>îòyâŸô”s«æ¾rŒÑ½%ŸSˆµÎ¿kêŠö(ðõPBQØbUì4ò—˜ªÿŠJÇ‚ [ßc IˆúÀui§&©"Ò§#H“,•0#¶Ó(&¬c 8¢–:‘†À$¼9Š&es ¨,9BZ€“ éºz„šÅgÙ…’hÂP,¿ óËÐDî=+£;@QÃJ*E\a Ð9qÏ­G£€½Ïï{­æ9Lœ9MÅ6ðcº õç˜D¢îuý>;¿À/QJ÷» Æ~®¼—†i4Ò'"×ÞõÃ8¸>/vÛBÁ‡;«£ß‹øw®¢X£¢|úÂ(àË[!‚*Ÿö‹_–„¦ÐÑŽV«¾Œ æD¿(ä¡\±­’F`¨bð ÌOáö&Ñuýì¼X|G8¬œ» z#ŒB겞˜ñBQÓj«¡ö©¯9¨}E^è<–Á‚!ÉDØ¢¤hÕPúKïanÕQ¶‹!D’Í0Q/ì`‰Â5bâ¥_ºðM¦¬àz"¾ãÊIºÙŸôÄ’´ –ÉÞ"X¡Ö¿%³…œ«´v›wÚh´@W ÍÄ9v†j¹M‘l]Âý+|Ý{…àöA ã J;Ьö³j¡Ýþ¢l É®§vóþkEš3ºƒÂÁ°Œ6 @Õc ô‚ÐäÑöÅ­;Ûs7“$Ý“MMåú ð2[7·µ¦È ,ÁbJ&Þ±˜À}³„Z.—˜¹TX h¤½¦sìÛ"àƒ2[¡‘ Ÿ¥#[¬Ú{°ÃÝjɵ »Ö_âË—n;­‡§=«TŽ´w›Ôk¸vÏÏåbHÇ&:§Ö£)OyÉÇx¶Åe1=_ø¸¥ÄÿmJ&òœÝ(ž¨gKh>XöÀþÖJÀDמ6FÇŒ™ÅÂèËMöH£í©0ûÑšsÏ÷;4ÛIÚ&:ϸec‘åq)çCÃêÔÒîyøl>ã3àOx·”F#ñtH½S/ŸÞ;5{ ïÔÓ½*c€GØ8-½PO(–&FÏq®ø@…aÞnQ»ÝÆ2|E)/qc“%‚¢«ô^(ÖÖ‹DÅ;™x Ø Ê³"ï-M¶W¨0ëGk9ÆÆaÐÒ$Kà+ÌuD¼÷]pÿÆìÁ÷ÿù¤6«d”c ;spPˆ½÷ŒA"…dۇ̲¯Üš*VŸþeÜ‹olñûÌ(’#‡AÈ0vµæ{Ï5eF¬nƒ| ‚£|sYE6dk(Tÿlu†™ÊǺá–ýF™BY`²A“G|Õö¸ùâCb79ö™Áá+_6VÎ!з¾há„*;]Ï8]’† §³.|H`æša²ü¥…j£Bã@:ö\CëkçG¯ˆåqÞ¿pûmO§Ûrü¿~‹â»x‚¼ð’+;ªßò8:UÉõ„Â@h+ =SF™“#‘=1äõE@LKû@è®Ø4j=5"a”®»ù"¬þÄGé"dg/’œ„„ΰÅG’Âpx "º?C Ùâk·í07¤Ô¡äŠÉêи„˜Ñ–'ûŒDpzñ)5ÝšpÏÿr¾¾ç‰ahgòcU*¢0\ôúl¸ŒAkÂCôTǘlÝd0¦m°Ï,yGæˆdkŒí¬6ö´ÒÓj:ƒ[¬õñÌbr(ÿ¹·º•y]7ô~ÅO}…ï~Òáí ´½Œ¢ŽÁ±ÛÁ³dAGøQ,­üdã°SNòÜ?¬ˆ_g•(Ç<îê2Õ;÷f‡†w9; ä{—@¼©xÎùƒ¿Ãôÿ…AÕïuÔ@?ÛÑ¥Å%ÔãPs‚/Ô¸7Ÿ/,9ñTyËé3÷ŽÅc(. $a—FÓÈz°a0Ó5y.—…r‹¯x¡Ü­ýl-ì#¯!+^ ~EU0„ ÷üuÊ l¢Q©ü–í^îøÿ!è«þ±!™‹ Î’ºP“4 "»MÊŠŠG»p'(=F¶wA»Ùaiv+[SŸõv°3¦ 5çz UrÑ.Üz| ¼ o,›Pû­-®š´«áê‚N2QèãêB²YëEF°öŸe-ag Ål‚?€)#mŒø¹Ær@ ˆßô‘V6†|¾,nâ3qˆæäTsÀ7wDµ[‡ë!pPõľ1¸‡ª•ɽeL/Dð!3Hjfl6³^¸ …ÂqÕ{pòYS©ŒL¬™F(µÏ(zCÊšr_ܽXý»iég$ÃtÊ6Äõ½ŠðpiSCѺ˩X?´~Š'óÌ;ê´BÁäù2¢7Ö®ÖàTÆ„›I=l ï+aëøxßÐl'`²n¨™ûqübõ.è» X ß–Ä÷çÜ=èHw~ŽFî€W x«jù(Xf_*p]Èc=Çš-Ô¶!"¸ ⌭ùld?ªuØEC"ÁëÀãx3½óeæ—J0• '²¤M¾1Ú(éué’d¿1ôìâ|J“2Ü‚^WºSD<³£Î¨zŒÌžÞcäî_]âc$쌰ãïÓ´Xôåü?ü‚æ8NØt,ä`’{Je”ŸãÀpΜ} ºÇµL© Ù™0'ˆóaðgúxHÙTC±úXžßähìï8:*†¢˜«€‚|V!¼CQ§ ÒAÇcò+ ·R»iìºAŠÿpÿþÎ׸f¥…ÌTóœÂ¸—»åøYËꓽ3 – ¨Xýos³ü…ÒøAãÙ":ß œfÇ”ýÁiŽF¡ z±*ó*ðãdZÆMGkßý±eD'2âéIÈ`|B餳IÜÈá²Tsi1qÉLDiŽ2†¨7qn MD9ßýåÁ`¡qôÃsX ‘ äuÆÒP8éô€ ` F@[EKå+øZiü­€SuqÙPþXÕÓ/æ»pË•ËxcO6ÍÇê.<<wþTý„êÐ'ÎAcâòKkh"c6¨õz™Y´¦bœÍ»ŒÙ T‹5‡‚:F¸b‘^£çÒrÆ’k–TŽ:lbØ ù…  ©›Ø¯ŒÍ®`³ÕÛ;Ï ä!Øà(8Ö á“õC>_L ¶Ô¨#ª¬$Ç–$gu„èô@0Tÿ´¥Æì<¹xϦõƒ€Þ*M¢§0aØ[þ2ìíh‰9fØû¯ ýƒ:íð‰æ«XÓsˆä÷æñ. ì|0£€øRdFÒhX:’SÀ$éHÔzñÛÚ |ŒÖó>‰Ý.ö6•$$þ*¬È¡ÓŦ°—Éñq<”ÉáÈɱ´²™Æ| 9„¦§Ú2Åêû6ehU“lßo)›4bªDhç ¾0=¿ló6Hû\7&ã$ʰx´Åš/=¡¬"Í}€÷™Òêðn#Ç|Æ#a‡ ‹)y¦<) /ö1že,—´ÝÓ@œãìk޽Ù(Ü."ÇG[­T‡A‰‡ :Ùvi- ¡èææ—ü±·m‘A±æÚÅ"®aÜú\œd¢FAdïB҈ŒCø*4dž=ÿ2™d¥©‹$‹ÕÏå-0Y‰+0\<)[uDímH[†¼qŠ´# Ì<•2N»CÒøc±°¤ëÌÂt•Š œÑê 9Ó{Ý—{ãPßH'Êá…EZøÍ<úUŽ×E™°#F‹K®ËØ~Jí>‡b½¹CŸ"¤}¾*1xSRÅjð¾Hä¶D¿[‹µsŸ‹ˆ)eF©èûÒ >ËØA²£0ë'—Šw_œ4¼J‚  r [}é½#‘=锼,ÿîu*h¬‚'àoü’Ј¿:þDÉ ÐBޯإ¢tÉ“ìtnêìnæò?ænVßøb…YSèf6À·v+¬ÐÇ)àÚÊõÒi@Á`»zßÓµ~MÇÍ[§žÓÔÇÉœÞú­ e0\# 5ˆ?J1‰¢µ³)d“8qÕ¿V»¢(sVa¬µ]+¿X ?åÊ»mv¹ÎD6C§M®%ԵϱØ8åW@³Y±{*ÚŒ‰Ûa€ùµàêB‚AïcÆ…óQm™yî9m™9sIU%_a =«¼sý̰zôÔ„±ðî3ƒ@5E7>áSy"çÈö¦ÆFÞ2Šq¹dYx.²±ŽAp#`].¦ÉyÔã&Ãw*–Ûqgϧ˜Ÿyy$ |éú{¼PQ$·÷N‰Þ5zÉ`° 0BŠE,YHA&iÂz¿ ̵÷t@$Ê»¡ÃZ2?oÿ$ /¥k§`"u‘B#Nˆt ¸¤4sáYV?|õEB=a˜²h¸¤’y¢DG°â"&$•wÄqM£:ì™ðôÕ¯I·ß½Àv˜‡cdíc… LÑÂ$Ú2Wª¾«›6§Gg]5luÈ´XŒ•/ªGC` ÇUŽw×2–‹ÆÒ£ÍQñž»vdÈš<(]Åöp‡†/ÔÞ>Ù™¥øàêñˆqðS+V÷NØdn^ÌqÖ'KcÙáúŒñxÊsÌ&Õ.t…e:>DÄ~r{GÛ¶xª”š4Þ«.CoÊê8èlRX޳EyÄŠ¬„8mî!CìVEãÅ–UÓS·î­~^£’Áè鮨Ç'Þ‹éÕ˾戞ˆƒ8bADq˜ðCij9RÃÀXšté=c£ø¬À¬v|YZÝbõŸõÝ)‰•ÊñÏ"N…î‹5¢eÊš Ù–¬¼–%#‰ùo§¸Ïêj„ß¶…I!ùñí"Ðà[ØÓ“û8‡µ1ÖŒÕÙO,ˆAó¦m—N%4ºAÆ Lö…²rØ(Ô>tÝdßÒ2žöLPduUYF× 4‣!‚Ⱥ¨vÆï†Qu±O„:<ƒ#%ÙÙ P{Q\ÄâtÒ†WmBQeõïF„«I“ y:äœ]½:_xÛÇÞS–÷-l¸§‰oHB² ¬2߯‹ÿ—a~*°êv3TƱUAô°g[pÙûvE“›ök¢—HÀ¼¾]ÈͰ–‰EZh¿ÉDŽºe8æ‘7Ô[5ãý{ßÔ„j›H;7‚@Nœ¯>°óƒõ»>T_œ__xÇ…ßmíÜØ]ÈúwÎî–ª Ô!ˆâ0¨” ¥´oèÚÚ¡çk§/×.;'ͧ$ߨ"™ìÜ:özÀ\ þ\ØÍ.3¹B!=TDq0z>¸]ºt·Z9“8Ê`ÊJÝžJYàKiô¥¬¨4–ö8VUʱÊÎÑd×z¸ê® ã¬Ôx2òÛÏú‘L4•¦›€@زñÁ8¤-WÝ^‡¨m·ðE–´sÍí=·vw8êúúê°N ¢JæÆÄư¦‹çÃ4ÊWÙª Ðr×€ æ¶MkpÇÔ©EÒéÈ8"h´mè^׆`®Pú„ÎÖæ[EÈvSÇZç9½pëú’ˆÏAe(Ó„™­þT*‹$õ~•.@Fþ`ªGªˆ{£½mkesµ%0Ã6EA]B7žrYì>|P÷­¢ý‘(pª{”×´9ßçž,ƒùàÄc²¥ptmìXkÍÎ@ʪ'µ?™M!ÚVå¨ ˜h2Å<ÀŽ 2@Ê…©u¸:¯: $WrÀ Fˆ™<+©žlòÖDÕ+¡P»¥Ò ©0|=ÃñA¿§­ø »)TáÅÒþ•–f"FR¾-yÃH49€@{s$cC®M›¬°&©Á :°þMÓÙí ·¹ªÓ˜1èá5½™ÒExªäâ½rzïç7\âÅÛâ7&šM7Îô»Žh‹»"'’¸‰qýds¢YÄ`ÇMì^bLµó þ¿néhïÚÂ>²’¿Ø9GáJÄœ@Sh·{=ç° pŒ'cŠoyëôø–'œKä[–øù–lªXë<ƒö{cª›Ù;†ËAÓÏ–­T—²^ŸÌ6FY¨pYãRQ]’~&‹ìy*IÖÊ¼Ó »—Lß|yuÒ2’oÜ8"‰íú†;k"é`q²Úƒ e³DC)hhx„• ê‡n[éØÑÚäf¼õ%–ðœdJÈ“Bó07O>©Ú³h> 4DèÏ÷¥û)tºl¨%ÕÎBdâR¬ùÚ'“hù!ð,9e¡?·bcKëD®Ä«S)GG#—"T˜ù¤›åkJ…§õ:eò1•±0ÔË i:Gü¨qÉÀ½˜ å¾3Öz–Žã¹žîû]ÆY( U[Á8Ú…*3ûDÄ~C¹e ÑÊ Âª²ýAžX[ÁÙ>–ÆdÀÉ9Ë-mœ ü¡HÜ›`£ÃÉÝSqhhU§FŽb}¸€²ýQ{ §páòG,˜IXbTοsŃÕ7¾Ø‘/Ô.ÊìðmŒ{Ú\ÿ-ïi3þ¨ë“ëß–°ógÜ‹jR±V±Î1ºäÕ>~³í‘s¥ÃžÓVÁ0ö¡Ö,»àÐÐF m[G±æú”3ãpÊ0U§YÀ’cY XŠx”…>D,S%±ðò5hÁ2…½-Ö.oÉkÜÄ„ªI9”œR –î¨Ñ@¢Þ?À]òéÙ'ûÂZË?– ž2]IZ~x¨PóÀë:˜Êõû^)ÂA ±r¢îŒ°=ùBà³)êäQHzç›ÊE G!ÁÊxˆY|&ú±$B[X8eÊܪ(é'Iæ s¿²³h ¢Á8uèL¿Šb»§‚ efÔ‰bßÎñÛÊÅØ¡êïuaù½÷Y§X,V±Öçs¦?>T¡&»ÈüGÆÊ¥h}Ðú„km'ûúÄ µïØŠ‘!z+¡­R”žP W •älwÃjò'­‚zdÉ„q Åë#C!uªðgnb¹eõ_Š ôµxƒTu¢o µˆ²\U 4Ò<Ñзhþ6íµö-QY” ­/ åIË‚kèÞ\Ò'7;JÜY*ãÊWR¡VªFÄèêk³| ›ñéRΰ€J7ñ$Ñ} ©&jK)+/Ðê ùÙÈUWJáVª\fÚ×0W‹ .õ'jĦ›4O“œ{Ûhµ~µâ²JÇ&.²0l·k3ÅLзMÕüÚúKd5+ÄU—ÏÍxùhA²D3÷^6ù»íËF"Cñ³˜Þˆk“f>àð©§Å€8Ò_J)´‚üÝ4!9¼ÄÐVê•2ÝöÑr>ÚBÉÎjGÏC…ž[ÖáȲןÈ۹|aæ¿S^~è,Ž|ñªo}®T¿œr+Ú,ÓqDS#<‘h.Ž'’ì‘Ä€ONeI˞˓CŠžž¾¯/IC'–ÿà«grÍùBÇ«OQ ­ÞÞ3¹p¾påèÝ‹ö ï¿óiâ0(¥õÔ£ñA¨§ã[Û°÷ë?Sòåfªè,UÎÕqê_ÜźNý+¶í:þíòò•y¨âŽ?^ƒUŒžý´™Î¢Ó„»’n=õì.ü5tüŒ”ËþñZ¬ëpÕ]WÕIIʶ³a.œàæ|qöûjÊ ô\7Q¢S^Œ[£ÀèqûƒÿYv—ƒãóóé_H²Sn<„mA +UUº"µ¾ð+½»Wú{𱇸¿ÿøÌ#Ò_˜Ÿ³t°dJI83åÌ È2]ÿTZ€¡™àþØîP›Ì„M@O3›,˜Ö ÛϼÏZXJj?su¹¶¹¦PE°mä¼_5½óþôãÖyWø;kßwèÁWä°üj]'°9<Þ¡“?;ÿûËo _öîpã[¾÷ãr4É Íxoï‰ÃùÈKŽŸ78áf9Š­p6ÒÕ+.Ëð-,´K`Á1½Æðà ´—©úeZ"`¡,¼%¿‚šiip ¥eÔgèK¸úéÚoU1d4fUR,@9« ÷¢‚'†ÕÙvöx’CˆDVøçF“çÎs”,éØVω)ϳ†Rx¡++|Cëb¶Àïí]j±´7ñ èŠ%ÖÉâ,àš\ínu\?¼¹ ºËŒ¿òÌU]•]{ ð{N¶Å](ÈOsj”i9éPsaz¢®!‚Oƒ³ÔZ'ÔG,*XŒ¥Ö4Y¥X3Þ*©\ˆ)gö™Nsï$©GŒÃ…e4NÛçÆ©2Úž”S/Nh0ëymœ¢9l&ݪ°C§4àuOh§åcaáX©öÎÉ·óe‡iÖ Œè€ÓrM~Â꣞%•¬¶¶dVPw²·tnRVÝÔpD§šq¸êׯÜÙ5j‡gUx€Ø"‘ ÊóXwaFô>®¡…©¥»¥rЗòA_ÿ–Ô2vwmíÜAÅ«¤‹;ßY'Š+P>ŒôXHÒnÕS½Ø•Ë^2ü0cÆ+wjO$])¦2ñ(òH4T1FQóR˜J-IØÏÅÓ!†Ò£zÓ:6š•y”DÁ.£é 7Û\ÔÐ;CoØGÏW ƒAí!©ûât¡£ü>FÎÓ{§L9ÇR På4øP@)`Aœõ•*¼-O†Æ½‡É•îYFå¯nDñ¸†6ø¹ðp¿VUõ3>|ø?þ®ïèš_à=£puGÕUoŸÂ1ç|ïW°éXÕ;¾¼—Ü”gEGúsá…ç»)3fte^G™ßóÓu®Ìk×|ï×YJ}ÛÚG«fFGÒá¥çWPVlÎκ˜R1ÅNmÞñÈæÙ:•*Xx~îó/¯Èé.@Ölzpý{[·ÍN… šÏ×>Ú|‹šI@êu©ª_îª!©W\W×pÄ•wR/Ÿ}¬•:‚yß´þÕÝã:•:Ö|~ֳα-UoÂyµ¸ôüÌÖ½­j&f’´Å竾ÔõY3‡è£¶ŠÏp%ÏÂäpóëUUÏV?ÿý?î«#Ç,Ûpretzel-2.0n-2/doc/project.report/manual-intro.tex0000644000000000000000000001061205653770746020753 0ustar rootroot% % $Id: manual-intro.tex,v 1.3 1994/10/27 18:30:33 gaertner Exp $ % % Introduction to the pretzel user's manual. % \chapter{Introduction} Prettyprinting of source code is a field of heated debate in the programming community. People like it, because of the distinguished appearance of programs and feel that prettyprinting is a contribution towards the understandability of source code. Others however tend to dislike prettyprinting. They say that different typefaces distract the reader's attention and that it is hard to adjust to a new set of formatting rules with every new program read. A weak point of most prettyprinters was that they weren't flexible, i.e.~the special way of formatting that they used was hard wired into their guts and not easily changable. Research in this area however has shown, that the style of prettyprinting a given language can be specified on an abstraction level similar to the language grammar or even above. This makes way for programs, that can build prettyprinters automatically from such abstract specifications. ``Pretzel'' is one such program. With pretzel you can build {\em prettyprinting parsers} (or parsing prettyprinters, as you like it), which are a special class of prettyprinters. Building prettyprinters that conform with your own taste of formatting has never been so easy. Don't however try to find the ``perfect'' way of formatting a certain language --- remember that this heavily depends on personal taste. After all, the author's dictionary defines ``pretty'' as ``charming in the minor details of appearance, but lacking the final touches of beauty.'' \bigskip\noindent This ist the user's manual for pretzel. It contains all technical information needed to write and generate prettyprinters for any programming language you like. However, it doesn't explain the prettyprinting method used by the generated prettyprinter. This document is meant as a reference for pretzel users, who already know about this method and are sitting near a computer terminal ready to start. Novices are requested to look at the main documentation of this project, where this method is explained. You should be familiar with the meanings of the words ``format command primitive'' and know, which ones pretzel-prettyprinters can understand. The following chapter describes the technical details of pretzel. It starts with an overview over the concepts of pretzel and explains the format of the input files that pretzel generates the prettyprinter from. After that you can read all about how to invoke pretzel correctly and all the remaining steps to get an executable version of the prettyprinter you desire. Finally, this document contains a complete example of a pretzel prettyprinter, in this case it is a simple one for \PASCAL. \section{Other Sources of Information} The main part of this document was taken from the report ``building a language independent prettyprinter'', which is the main documentation of the pretzel project. It describes all issues involved in the design of the system, including a survey of prettyprinting algorithms and a detailed description of the prettprinting mechanism used by the programs that pretzel generates. For people who want to try the system immediately there's a ``getting started'' section in the {\tt README} file of the distribution. This tells you how to install pretzel and test the given example prettyprinter for \PASCAL. \section{Why ``pretzel''?} Is there a special significance behind the name ``pretzel''? No, there isn't! To be honest, I had severe problems in finding something appropriate, but looking at my dictionary I had an idea! The system here is a generator for prettyprinters, i.e.~it is more than a prettyprinter. Looking for more about the word ``pretty'' I came across ``pretzel'', which was the word that immediately followed it (at least in my dictionary). \section{Author} Author of pretzel is Felix G\"artner. If you have problems with the program or need further information send email to: $$\hbox{\verb+theedge@rbg.informatik.th-darmstadt.de+}$$ % % $Log: manual-intro.tex,v $ % Revision 1.3 1994/10/27 18:30:33 gaertner % Added a passage that you _must_ know format command primitives % before reading the manual. % % Revision 1.2 1994/10/25 16:00:12 gaertner % Added introduction paragraph and sections about further information, % the name of the game and the author. % % Revision 1.1 1994/10/24 19:10:11 gaertner % Initial revision % % pretzel-2.0n-2/doc/project.report/chap5.tex0000644000000000000000000001762106135737633017346 0ustar rootroot% % $Id: chap5.tex,v 1.4 1995/04/20 13:18:48 gaertner Exp gaertner $ % % $Log: chap5.tex,v $ % Revision 1.4 1995/04/20 13:18:48 gaertner % Corrections proposed by JS % % Revision 1.3 1995/02/24 09:58:18 gaertner % Final revision (including figures and index). % % Revision 1.2 1995/02/21 09:37:28 gaertner % Changes \mkWEAVE, \makeWEAVE, \preFLEX, \preBISON, preFLEX and % preBISON to the relevant terms. % % Revision 1.1 1995/02/21 09:31:12 gaertner % Initial revision % \chapter{Future Work} \label{five} \label{future-work} \index{Future work} After having finally implemented and tested the \pretzel\ program I have noticed, that the program doesn't do very much at all, although it suits the specifications that belonged to this project. To enjoy beautifully formatted source code you still have to construct your prettyprinting grammar. As is seems, the work of fine tuning such a grammar that the prettyprinter is able to handle the last formatting detail you desire is quite tedious and time-consuming, especially if you start to build your grammar from scratch. But after constructing such a grammar for \PASCAL\ and applying it to a few everyday-example \PASCAL\ source codes, I was astonished how easy it was to change the looks of the prettyprinted text. I think that starting with a formal grammar of your favourite language and trying to enhance it and transform it into a prettyprinting grammar is surely a better way to reach your goal. I suppose that the \pretzel\ program could be the right tool to help you with this task. \index{Omissions}\index{Prettyprinting grammar}\index{pascal@\PASCAL} \index{pretzel@\pretzel} However, since only few people have used \pretzel\ until today there will surely be a lot of things people miss when using the program. Now I will list a number of omissions that I have thought of during the last phase of the implementation. I have listed them in order of increasing severity. \begin{description} \item[Allow \t{/*}\dots\t{*/} comments.] In places where the user has an empty production in the formatted grammar file or an empty token definition in the formatted token file file, it would be nice to have a C like commenting feature with opening and closing delimiters. The `\t{//}' comment delimiter isn't nice if you want to add an attribute definition to an empty production. \index{Empty tokens}\index{-@\t{/*}\dots\t{*/} comments} \index{--@\t{//} comments} \item[Copy comments.] It surely would make the generated flex and Bison files more readable, if \pretzel\ would copy the comments from the formatted token and the formatted grammar files into them. \index{Copy comments} \item[Generate \t{\%token} definitions.] If one would impose the restriction to use only uppercase identifiers as terminal token names \pretzel\ could automalically generate the list of \t{\%token} definitions needed to identify terminals in the formatted grammar file. \index{token definitions@\t{\%token} definitions} \item[Using more than one prettyprinter at the same time.] This problem is closely related to the question whether you can use two seperate Bison parsers in your program. As this is the case in newer versions of Bison using more than one prettyprinter at the same time should be possible. However, you have to use the relevant Bison options to enable this and it would be nice to circumvent these problems in a nicer way. \index{Bison!using more than one parser} \item[Include code in attribute definitions.] If you want to generate an index of identifiers during the prettyprinting and you don't want to do this through text markup, one would have to have a way of smuggling additional \C\ code into the actions of the flex and/or Bison files. A clean way of doing this would be to include the code in the formatted token and formatted grammar files using special delimiters like `\t{[[}' and `\t{]]}' that normally don't appear in todays programming languages. \index{c@\C}\index{---@\t{[[}\dots\t{]]} delimiters} \index{Including \C\ code into rules} \item[Change prettyprinting grammar format.] It would be nice to be able to insert format commands directly into the grammar rules, like for example in: \begin{inp} WHILE expr DO \fmt{indent} stmt \fmt{outdent} \fmt{force} $\longrightarrow$ stmt \end{inp} This is a point that effects fundamentals of the \id{build\_pparse} function. Other parts of \pretzel\ are not involved. This is a change that would be good for new users, since this way of specifying the grammar is much more intuitive. \index{Inituitive grammar format}\index{build pparse@\id{build\_pparse}} \index{Prettyprinting grammar} \item[Allow changing output formats.] To present, the \id{Output} class that does all the interpretation of the format commands exists only in a version that produces \TeX\ text. Though it is easy to change the implementation and thus the interpretation of the output class, it would be nice to be able to have a library of different output versions that can be chosen from at run-time. So if you want to prettyprint code with a prettyprinter, you not only mention in- and output streams, but also how the format commands could be interpreted. \index{tex@\TeX}\index{Interpretation}\index{Changing output formats} \index{Language independent back end} Joachim Schrod suggested to design a new \CPP\ class for this purpose called ``\id{Interpretation}'' or something similar. There should be a default interpretation as abstract base class (what would it look like?) and subsequent interpretation versions would be derived from this standard. The prettyprinting function would then turn to \begin{outp} \res{void} \id{myparse} (\id{istream}$\ast$,\id{Interpretation}, \id{ostream}\&); \end{outp} \item[Include files for grammars.] As parts of prettyprinting grammars occur frequently in many different programming languages (such as the formatting of expressions) it would be nice to be able to include files that contain these definitions with a simple command in the formatted token and formatted grammar files. On a more abstract level one could think of a notion of modules of grammars, i.e.~parts of a grammar that can be called with arguments to suit local demands (``grammar templates''?). But it is still an unanswered question whether this is practical, because of the lack of method to specify the interface of such a module. \index{Include files for grammars}\index{Prettyprinting grammar!include files} \end{description} \noindent Looking back at the project it is quite striking why the prettyprinter generated by pretzel is not built in a modular kind of fashion that is described in chapter \ref{one} and visualized in figure \ref{pp-concept} on page \pageref{pp-concept}. This lack of modularity possibly has something to do with the fact, that chapter \ref{one} was written {\em after} the project was in the design phase. But this lack of modularity has the advantage of not having to define the interface between the language dependent front end and the language independent back end, as this part is hidden within the \id{Output} class (see figure \ref{pretzel-in-concept} on page \pageref{pretzel-in-concept} for how the \pretzel\ prettyprinter fits into this scheme). This makes the implementation more efficient but less understandable. The extension proposed in the above list to introduce ``interpretations'' would possibly only blur the concept further. A new design, based on the fundamental distinction of modules, seems a little more promising to me. It is clear that still a lot of work has to be done. \index{Lack of modularity}\index{Design phase}\index{New design} \index{Work!a lot of} \begin{figure}[htb] \begin{center} \leavevmode \input{figures/pretzel-in-concept.latex} \end{center} \caption{How the prettyprinter generated by \pretzel\ fits into the module structure of modern prettyprinters.} \label{pretzel-in-concept} \end{figure} pretzel-2.0n-2/doc/project.report/report.dvi.gz0000644000000000000000000022557306236071216020257 0ustar rootroot‹Žrx2report.dviì\ p\Õu^í®¬`L )u2Ø&²"í®e §Pa[ÄØËüš„·ï]í>ô~ÖïÇ«Å:PÒ6 ž/^ÞX 2-dRBœF¤”fœ·Ç™´%mâÌÊ”hÚRµˆzι÷½}+˧”‰êIfľûî½ç;ßù¹÷ÝsßH·Ý½ëkï_‚™þ ‡ÙõÚ¾Wñ½ {úû{»zº»ò=—ôtçs÷¦Žñß,üÛ›þëTj|ïÛkR©½é)üóç°äÚñ©oŸÁðþ}3žùÞ¦½©ó^ØZ¯,PÍâXOîÕ E_74Ý*§ ïTê_Íw¥îR_ŸY¿öoâQû³ÖïKµ«¦Ó³êÕõ†b•|¥Ä‚޻閯*Aês ƒ?¬`ö†½úCâíW7TæyÙ¾ÿªUÝâsêõ©•î¥ãøoWêÏï¸k¦ûú/\}:ÍÿO#ä_̶_Ë },ȼòùõw?»0«8žÅœññ©7ÉÍœsûÎ:RïðÿYx©ïk=uñojqª úþÓÉ{çVuí}Ï‹ÞŠŽ¯8ؼ²¾·íüÒ¹8‹ °zdê­¿=óÞ¿P>ŸZ€°È>{¿Š}}#gÌœoåÞ©ÓàÁiòaÿ_—u·‘ùÔ•«L °«öî§ûwpæÐï^™ñ{žîgN/r\ïá‰n[ÜáC€ÌmÌ€ùí¼fm¹¾áq|Aþ^Ü =r{û±|TŸ:µ¸tÿc†â1×kdÎÝÏé“k6ÌGõMf…žâÁÃ.ã¾c&ü»x"­ÚòÀú¬1<óóÿcɵ©…ÐnaL¢îCE×sÕ«O‹óìÝÿØLÇG_»¥7$ÝvO ØvjÛžõ‹6Ý%ÑM(¢Ù!Í|Ï“/йsÏæ ¯8vª÷ÝÊT„IX)¾Wlª¡íŒ†Lã¶Ux‘ÄH|¾ò8¶f/~”©ÐaÙÒUÅà[-]h kÛZÅ1]OÑ`"r@)ŸþÇaxµdCshÝ$gP ˜² <Ç¡Èx™ß§ |ßýä‹1Ýñçâ*žít™û—ê]¬KTrS£: Tªñ£t0âØ&WähÀS1™zAc®êèOj'Y…W^çºÇݲíÚÜ>'áaI–Z¡kûŽÊBÕžX¿Xc]Á‚Œ‚ءÎr¼êt Ûº°3`’Û4ånÍõ˜¹¤ ƒÆI·Ù5›<6æ ÎÃH€u)¸o|phКØ×ï9öÄÕ4_Ešïjû`îþ|½þ'çB#jÕSÞ}q³dž"Vìëo²ÖOß¼se]ø¤è§{ºà«öyè!Dòè2ÐÎ<¾Æ6MÈ ¾:HßùHßè8pNüü8úk<8çå³@܇àDEaÍýÓ€1zTÇ6 )(ªsÀ´}`+jw£· Aê“ï;d%iz[¤ÉEÒL4¥ @šºÅVÁ“ŒºAûáLJٿ+h¬jA#Oh hšŽjS D"&lzû'# séo¤@€lñ§†,fÏkÌo¼~üc3œùò™=Ý-®$‡1 nÝz¤ ×c8À4wðoŽ.tÜ5™<?€ÚÜRÆtqƒîB2U‹2ÞV‚ÔáGNLÉŽF.AœtèÌgÑè7Ù°":þhæäýÿ¬\d/HŸrÙÊ׊ R= y…‹pl …ë,-Hw:¾p’å[$ËÏ+†ñVÙ.WÔp”Äj_rßñ –¦Ð"L!)ÌFɼ~ûÉÌñ Â/'êÊQ…ß,”t/>äØEƒ™ ïeœxòö&œwžœ· ÈAûý'@Ø=qþp÷ÕëŸ+¦-†¶º”‹õ¬VaÕ´°ø‘žþX-Ó9¹’é´Ê*^b )èxô½§²¦²ý±áæâ…”„lЪø7tÂnÛØÐ©ŒÕÔrÝ-¨µàõÑfÌ|‰<'—ï[´Ö\½¿:\[d›ÉÉ®˜ŒðAm‡ö(,Ø™Eø<îÉÏ|P´¾I„B.Ј‰‘µ'&Bæ|‹Ìy¹3cšŒ6ghË·׈Ýå mò›'¦´ÿ[| ç!ò «”Q¹û¦Ìõ€¸Ó/w£ÜÞ·ðÄLˆ¿2A¼ôƒH¼ƒÛ£ÒáG¢.è[bŠúî&|È€…´X7¦˜£ùùa sñ›_ÐvYîD‡m>Ñ…+YËŠ~©”Ø­ž?gˆw¼ÌÎ_BŠÞ) rsvG0»ý€¶†Ó¥¯‘vEWÝ 3þÙ]{ï³U 'Y ')ÉŽZ_¦Äñ?‚Ï(÷­øéÙñ÷äÕT]µ§ûUe(˜½0¥¸ªbL/2Ń':¬-Ð §vzÕ×Å©‘^õ·È,|"-í#xÔÕs‚ì™ß?^e'éòÝÍ]‹<íZl”µ´qÑü®)d¼‘‘ÚÛwV>ßÜÈÈËŒÍ&£.xâý sUýxEâÝÆ¸™ ççî_Ì|ðG¯|d,y†Çózº¿sݺËù´øÈ¤>¹ûÔîè`ZÀlº lÇô|¼ãC{ž|QÉ £Ån±G¼°*ãõ†'4pÍTSÁk/xícÿ÷;QPsÛ9/÷j¶EŠÁmvÄ\dÏ…W)–Rb&ž8Ydö÷ž<ȉE>¹ou-N!E ¯Ôá;ydw°„4¬>%NÄ~ÿ_Æzäѧô±}ZðLâèÓ8Å»™%•}ÝW&]¯kôt{ÍæMÃë6 oÙÕö¡{¯ŸÎÕëÑA©ß‹^i{h%…Ÿ+³ ¿à#OñóuÜvFÇwµ1» @Ë l9 îÞ×?jÙ¼j0M¦Y.ĦŸo{­Ð7ªT&®>À,Mƒ÷;÷g «¢G—ëECÇLºRžØ×_ƒÇ‹¯ûI_!zŒg\ð½Õ‡ÁYä̱ä=õ Ï"ZEƳþÊSÇõ©>ÿýû¦· à·Z#óÄÅÑÙkæðjÙæ#Šn`MWm³bÔš‡µ]²ÅѸ¥àº 3Èúøˆí¬¥ Ð+n]à²>{ͶƒïËò:n[xOÄÛ–è/îY¿˜áx]A‡þÊàÇÓþ6/+• 4¦#ìÐ1Ö427Öt*±Ð-茶ߙ¥£JðLºÁ: —ufwÓ3x"žÃÌu’§2^ m|#ƒ¬qÄ0ÉòT±ÂM…ê[l*]ÀãG4Ž‚3ªñ&ÛajƒÀ ‡W+L.¬ÅŠF_¶\×7 “Qñ‡S+î†qŽä’DŠá0E«qÍF\» p¹ïñA!qÕ±­RTU²ÑW3£zÄÌ=9Ýrý_S%wNE”Ø'p€Ê$ 4]C´Ei „,™³1¶"Ì'#kdzÿLq%[Ñ2_ñçí¾ I³©—ʈwýR Œæ^Ú…s§ñ,l£Æ„¬_"H•È™¿YVDï“™îvÐgNHU(@cÈ0j¡ÂÅ’ÕÁWí¬ ’@õ"<*r¦*¾Ë–®B ¤O¯Lq,¦…žV°_9°‹>Ð’¥À 5ܾ°lkEì®d)!N-±nÉÖÆq£h:RÏ XãWïE¿t"p4Ð0Ÿù­·SK/iÙcÒ{ºVY‘OëØ`‘…”õ€yà9Ša ~r+HYò£Š§†eД ¦äví•· á¥=ý}…ÎÉìÿp Íei½h+Ö]t¯b€'„èðWÑ-€¦mP¦ƒ˜ NóƒTBÓ˜ýÄR;ÈßRq¸ÍKðÈœî ì¦ Z6  Õ8bFÚÈÜjG¬52´+kõ8«…”Ç)yÎò0 :ÐÀ‚ޱ%O.ª$ÛCÁ?c´ØY-°v‘`ô º74Y$ ?X…è zä?†¡"ùÐu¬Qo|]VÙWWa|‹U9`M¥W­pd¾uGŒYÓÀ¼½?T°“dő롌 ½¤:F¬ÙÁ‚'•i“ÙËoÃR¬µXž …ëºÂZÜ÷Ê¡n…¨Âð¦ñ\ŸpúÊú{q²¡*Σ…ð§Âužì€²ØôìþŠ"ä|™4rÎ.1JñZ"ßr;tÝ7Т€ÈÚi“¥‘^÷¯ä?D–‰N'¼±ÎÞdžX¤4Ó¬Œ²ï™¸7Œ@, 1ï€à|{oóÚŠxÕ x|ý71“Ãøf&'o[ˆŽü ã{6«þùèjw¾{#¢Û" ÕidW~\‘­‘ÝGÜ1ôÍEÆÜ®5ˆ¾g½4hÅ©.»Îí3dÏm¯ê†!“DªBk¹y³C¹yý ÌKw]Dq˜A ©H“Ñ(xd®‘yðgó*òØ/Cpž„çUQ¨¸aIßL6GŒÀ":,Û5átB9p%°@!Yå`x„\ÐNgòò ÷óÞÀвÞJÿûßSÈ"'ƒ+Q·¹#%®üÀõmãÉ»'B±€Ø6orêRî?´aЋW'‰é7cÒârS!C0lyt†zbD™_òþ 9Ò2ZÐ=ìé=Ë£nzÌI…˜0Þ’9…£‹täÁž¢µ`´Ù”¸F£5§od.Ê'ã9Ðê‡÷&oÝÀþ—¢ã±BH—"ų0B¸ˆ¨LóPäM4h«Þ°Ÿæ=r·îAkÃ.yÝøƒ¥° `ˆïFY}Ëö Ä® ½8„D  —ìÿáîÚƒ¤ªÎüØÝ<6à#¬Š¢ŒQíAy9¼Ê”(£‡Qîtßž¾ÒÓÝôí¡b0Ñu7j·^nlo fWÝ‚Òk£K´|&Üì–f³ÑÕÕhʸºFcÅWt¿×¹çtÏ þ±[ù‡G÷}žó=~¿ß÷Ӵ׎ߋ«“Ã_Ø‘Åv"ß;‰¢ ]SǪºÖ*ÅÞ ½nóœÓ]>ã %"ŦܷÜÜé“$Ù Ô 4yziïX;C¡ÃQî6Ê¢®J‘†¹ ŠÝìˆùRÆ* ›7Y¨ssõX>R=}ª*­LÕ›õဠ¾Š ¼Hâé¤Ñ‘‘g± 3m5T""\¸á‰’ ñ«ʶ¸£5 * k Urãððlûq?¬8ŵu@BgVˆCÂû#¼â»òC`g² %KÜŠ=±ÍªìPÊHÛ|ºÎZó/ð€C€;G¤5`{ån›C|Q{u/>Qù%‰o¤f7 <}¦R³]%¾)mÌxJ}ÃL$¤ŸÌ»¶K‡Jk¶zªjdíN³õܯu—gHKèîr[ÅÑtH¼ìϨ ŒZ» þqF%€?gÓŸmm•±kïÇÍâæð_gÒ_gÌà¿ø»™ò¿¹•-ý¤×ПD°³ 4Uý|.xìo#¢óä\À²4†„i›&é\…Ë)((€iòŒÁÝ<†œ‚´1Å~•ˆ#Ø¢Ò€•`޽WÄk-¨ÖìD´'¶û±|!È}…Àêw½¦Rƒ´1zÂï;³”” á¦m(4kób׊ ánpdÚBøVU“"Œ…›H È|Ý ajwöj‡~Óꀠù=cNeææ`ÖôŠ7vg²'^ìûhù’Ó;½ÈιÝå3i²{âpÒÇÍã…à´¶™<§sa®w&ñlžÈY` =ñ¸BGÒS™9Í'ŽÌ_‰£Þù Ý{ˆÍñIh``K‡^²’,Ì}É¥x1*úrðÅ,JQ½ Ìü[/í„ŸÎæ$²W£ë½dáÖÈ)Çž[ñ¢¯^}Y5zæg0jsÄS”nØ(u¼°”[” í» B·¨Æ¦·w‰„+ž`š1¬Ì-/Á¶ÙƒÇÓÂÅcÜzÅÖ-9ª’”/õfœ„H«±SWv Årü²É”GæRÕèÂÖ“•©§Šòo©FÍ[e1s:ûý†yñàRýV¢kUêªf0ª;(œ^ó ^®±©>Vz"ö4šH?2a±fH¦0š£ÞY5öÆqàƒ\Ž‚l·ô°ü4ö¬jÿªuòŠÜ0;ê‡H#psLh†&«îÖ ÌwK'Øò´ÙñPdZø‚Ò/—¬a>Y[s±ŠYtúÜFnÿ;8ˆ¡ iXÚ"÷ŒlHs¢É¹~‹=­o<:wK B {º3î †fáã{cãÁ͉36£DØ8•·ˆTU±"*gY ,ìⳘW´ Ó*[—mB;Á56Oäb½æ%P½ßÆÏ¢K©‚“€üýMÏÕˆ®(¿ñ§P¬Yyq'­ ÜaÂó½%,ÓæáyФŠ&}Ú[ká4;6A+KB`¾•ªíÇV?Ööc«ß‡ðšÃç·&è2Ttû" !•8…œb½^ ÎURþáuósþ¦@´@H[[I˜P-2JëÁWÕCŤ—uÞC‡Å.Îåy®¦|õqVß›OLæ°TÊd2¿£~Ù%÷Î+‘n4ש”lªøé½©úý|*['ünRÈfb•¾ÏÝØÓÈÝ•°6Îë'`T=ø6Ýžz®™-V£OœšÀcùI°rÑa kGÑ_ƺP”-Š¢ÀH¬aÜ fâ ô§‡ ’lf,Á\STLs<ã2Ö`!TcWgë•B Žõ©¼É,v;àtµM›A‡ˆ €hÔoÆ-qh'(.:Í ©œöa]xÂ<§Fh¾l²¾½Ý  •*±ê?“Ù³?MQz–Ðã‘F/øÇaDéÅ˻νG¼ßSÇ.[ê/¿øÜ®®o,¿¸siWçÒó77í:ì…Úì¡rõX\ º|#‹ŠR´™.‚ceÝŒèO·r¡4«J]pžo%¹B’!‡ï‚ïR—*ä¨äO] ¶× ˜jÿ±YýÅó¥‘"o¹\f–ƒ¶èr›FvDís *^O©Iü`ªtˆ¯µøc¹)ˆ Ïê²µcõo#Z-¯ÆCïaª.hj 7 &¥SÁ¦ÆwQ-‡­ëÌu¢VõFên ¾/–•I‡Ø dûÒ›fù"ˆ„VÒ!%¬w&°õ$—-×Ìx±Ÿ\å†Ôvm x ù´ëÅ¿©C5úî7‹VŸ0ÌñN’kC|#Ýröî7qðÔë§6pÂÈH€ƒ ФQ×u³!¢š~‡‘?[Üe'iS¸Uœ¯Fç¼oVÏãTõ ôiÓHûº±ƒ»ðj¤|ðDrg_؈w›¸Ø¸["ÜáGÈR+¾Ô@ô¯ç©O ©O_Ì ú­ÂšRÞ‹þ˜^Ia@î×¢ÛÄ¿•¶À†!UعÔú_ªòc½“9¼aÔ¢}𮄯ºððZ D‘R_Zb $1=ºUïUb1_þ3qE»T=!´¬v± ‡¢˜IO‰³–'¹X0'µAÍqx…m¢SpI<_b‡–¶¾ø8Xáæž];[gæd@uý,sÁ\ëÛHuÉÉÓJ“:J˜6èÚ䈪ÞØìé5„ÍÐdüA¾Œ—4rªë3ÑoL¼£ÿzøÄ‹¤?¶èxbTÕÈ#Ý u$2èïZgÈØ©¢Žˆ·ÖGD­&FOº[º0 8Apy뿸ɂ言‘ð>”Ëir×àxÐáQò´)d)%«§™¹©­¡õ(º·E7§…02ï$‰ì“9ìK• s×—£²I®!fûðy[û ô·’ý¦mÏR-1íxî/Àé1Äzl)C‚»P«±¨`ÄWͽÆé䈽V¯Èì†ÎHKU¨Š–t©Ç—ŠF¹‡²Œ-ò Ô]Àî«Fì<I¨>s§¥ZH}‹uM6vd¨íÞ¨Ë/íòø¦$áÄp§è¦óç›Gˆ[émªÉ;E E — V؃†rj¶OÓÔç¬ãý4W½MÑ;ê´-x±îí…€ÍõOQ¢ìÞ¸A>Èe ~&¡À'޾݋Kífƒ¾Z5ö½Pß®JàðÆiPáçzÁ<²vRòÀЇ¶Ñ}T™KǠ™Q‚v&Ë, 7Œ,ð…IŸÎ¾0‹ø‚ú}á /ËÎäË?»w&¿«)Ü™¿×îCÏn_àœÖ6iî²UŽå¶¸(R=QênÓ¦jZ±[,#/ááŸ""0®îôëÓk**ñ¶i #Ò&‡/îêNY'ÛŠý4«àÍp…HðÝs;µ2…½à{nÏæê¢™Ù-K3«*YWaÊÕºöߎØ\îR^¬˜QØ»ŒT&8 =©“’¾"ªrÁ'`@ Ë ]ß·4å2/L(ɵ®2”íÓBðÊ4µFíÁ£¥èk^æ0ÿ,9d˜_ÿ·š@q`µr—ÄHHGµVSŒ 1xÊß#]n¾K€AÈ·èÅ(*Jl`*f¯”ˆ (á»uŽÓ\šÃÏJ^«ò3CjÏ4¶á žÂr#6G{Ü}™8Ñåì;ȲìÝ(ž}éY¿P‘EÜ€óV5â¬OJÝ ð&R`ben±”wyØÒ™åuL·(%ô’ÆNEJa©HÌí¤Xn½_ÌÚÖpÑ?à`í7d„p­bØ?HÚ%&\}gèw¯¼Ï޵ÎÁÆ"¦dhRàÇW‘ú›i´5ùQW½FjDÓ°;=ƒ” ú¸`÷‡‹½in÷uêeµ)dVD¢‰Nƒ°Þ~ÐF@0Œ-àè³ÅNiú.žÚºlEƒ¥Þv}ƒA sTA¦1g£èG-tH/3€(¹ æ‡ y4åßv=’…ÒÕ«œ}ÌRÅ·š×¥*FxÃù¿aiÍNAèx`—αœ2Œã›ýû†`¡œP±ÜjôIê8°2¢„Ñ'¬èq–´©pE‰‘ÚÃ`—п‡WgÜ[GÿUÊLEÉG“¡ÃÚdaƒ'’ ‰•@ì—š†ÊÑ 4ù¹ïÕZ°Ð† Û±_WrÂ]4°a^ô–:§[õý¥µXšýA”÷àMl w0â–¼FÕ!ƒö3Îyð}Øñ†r®lÇÂ1wª©â½,¿½ÇzÝ­Z¯ób×6¿½gès0ˆ`È­7éù¼÷šOú0Œÿ§<¶É˜ÏÖ›ê–ò4úßÎWjÔ]Ë[?ðÂ’\¦ ºlv·T£‰—r‹BênÀ MèºûU¼;“¼…õs¥qt(gˆâR† ¢9w`Uc7ä6•†ô5õ;¨¨ð¯}úE^Ê!T1iØjMøK)×_U,8 6”ú©“—!4W£é5Ô¨J"H¦²è8;FŸ£rï(À Îâ ½¤™áÓ׋F»ýÀ²ùV§°{ 8g_]„¸ˆïDWDzÍ]…[g,þ>)ŒM¾¢Ö·Óµ+H˜ÎÈÔ•½¥TÊ.t×ýïÊ|ŽÚE{Ú$ˆG‰Ãо`Øežæ+¹Opâb = ˃ª{œmì d€qAØk¬€—òé¥T,7Àò䇃üe¯éÎC¾ÛÔ”J5E¿:®âEwÙ[c*››nøøùZwyøãªê¸†Ïý<Êè•*Þeûž¯õ”)[p&8âØ5ƒ àç=T~qÈöäÕ[+J>ÀûÀ¿:ùµ‚GÆ¿Ä#onÚ~Ì+_À€œT5ÚýF1-Àa½“,Rl,eSŒ•!7a¯2˜úß\ÇâQ÷¨½®¡öTÎü)Qe’ªbC2.ßâu£uÓª7ël\À¹`4bÎÔSÔV êLkئpÊ"ªINà?ºpX²h‘´#Â:€—\F–*Ú}®·»äÄrqšèVšU&Ê¡>µ+bô ý{^€˜Û¸ùä_˜ÁÓÏгÒQöfÞð„{Ç G})c¿ãÕ}û5v’ô:ÖŸî·heD†öÞZ6{Bôe‹ ÊG> ­~Ô: Þý(òúnêP,bº ‘3£}Y|Î.¥7Ömb)lE9k¥f€„|©Ï (R>Œ’Íàࢠ­äUV‚t|S|nA!]úþ\[`ÖŠ½„PZÇÔ°‚ŽÖþÿ5¤ª ø%nP.on*_2Àöµ¹iËö·¿”½_»;ÄüJð¥A=gðè0 ¢¼ñ«gã&2%—;²ÀnÞymhW’![z¡tÄcyMoÇEHÜtŠ×£Ýèþþç~ŽÖ'ýÏ…¬6ø`Iª©ªpCÓìG5RjXýVfÌ÷ü¯‡; (JW%ȵ{ B<^3Œ¸yß"À8gw¼NÃQrÅÙ@”ÿyƒtê3 y`Wœ}]±fõ;IpNAÒp¥!++²Ñ!U¦ß0öu!¶Â~òâ;¦Ÿü~øI±nË<rY®À( ®AЇš¤€þ1· eh?DWê—„³uÐS˵áî >W£þ£uZkÕǽÀ-üóiO<øÎIU¼¯tޝ§¿|Kzª 0ÛW£°çj‰QhŸ‚¡Y7pŠq¬Ô9ÙvÜpÓ¬)  ` Aæï‡çÊüœ‚ˆñÔÀ¼ÝC¿ñáãÆòÅBÏü…‰©Ôê6ÌÕösÎüÃ|NÒmÌÉÕ:••½Øµ´¸YŸÍ¬¹U8>4ÿ~¾êYø­9L`a1ˆ÷*ìËaUAÓõ5ß¿†ªfhz悵üøý³x…_„ÐsÈÍÁ˜¶ÿ­k…™×,z‹Þn'¸‡‡zhÛ™\úÉ^Ã&ƒÔTP„„Õº÷¼ZOÒÕžù !fAªõ[)F–è”ðÃßûó®<ý†+Þ;tJs|KÝÆäÚ¦?4žª¡'ÒŒ’lõµ‰ÓMíR óÔáðÉEá:6Þ…”ö®ÊØ ÕwMRX…kÞÂ\‰Ô;Ù ”+¹¢‡k™˜'¶{ûÜ! è,O9eõr$ofã"h¢om›¸ŸÂÏÿÉ<ÍÛ»ë æéàg„>&vÕª{v×âྮu™S¿sº¨ouVK{CQ„vò•ÿé]7-;ßv¿e”X†`Oå§D†"}J­ë¹ºX_&<îþ?aè ð†->³xÜVЄ«4ÊÏ©ëý¥OocQRÝ^õ/©¸”!ÆÐ™­ÆúúH@ç>]bJ‹Ê¡™ÛŠ %'•^Ù+E” Šá>VFo}5¶ùãP1gŽ^¹ZufØtQ- I¶ÁðŽ~í©Z²Aâ}ê?IÑʺëê®k—{_¨$M܆hŠ^®P`¬[¾Œa0à=q3Le×ösÝr( ]Òý;˜£u ¸Œgã/d˜Ô“{p)%`ê– CxèaOùhÔ¡ërï¡!Ýäì`(#¿{Lonßýž¥õBOÔ÷öí{ÒŒBš<žùir¯_ '5ä"ûPnÿÐa¼Ð-¹ma?Nx©tÌ×b,™‚…ç~[Úñõ•§»*¼ækøÓ$xò;m×’‡»´®K.{M)C½ó$®' ¥ŒT{ 8Ú9±áßµöÐÓOÁ°^)¼N\Ési‡}ñž¤W?-‘á*PÏÁ½ò_×á-N‹Á^+åzÚiû\OçOüï]O“K±/”ɋ̑¾ðäo9.¢qã˜á壤b§-èçºW:¾ ÎÐ͈ÏFFtçFcm¨m>³h4³Q'SmleR·ì]õ§#&ţ~L¬ðMC C uÕÐÉÌêϽoD÷§†O$=%LŠ®ŠK]AÔï^–Ú”ƒGâuÚa5ÄHÌú¯zHZ1Vd|L\¢Ù)M^C 'ËNQPÙ?$®m@î¹ÁdûW Sß…Å&®ÿß™-¼^ÇÆ}Ñÿß3aØÃ£1(‹NºÞÞu:ÿÔiâuuu==iÿõ à†*û©¦.¤þÌúH†-AÞk5ª£ÑÁð;h^"0—¹¥H)Ä“¸Ö’ž½P†AkÆ$Z˜œ²ŽÒ Žþÿ‹Ž4óÿÿÒ‘rKvûñ—+HóRX9ì‹[ÑQúÌÆí3t'‡O+ uY&»‘ÏšQÉè"g¡wItÉÞƒ; Lx€Vš|†5_Xœǰ’7»ÿá»…’ í8 Ú6D£q~lMúµŽÖNïÎGª·Ÿ•i¬s&dßà‰åÒí³®4¿ª19ð‹ÐÑcøÙ$bwVô¤À"@ëð›ï똦Á?pÏkÃý1m)–V U³:J®aCµ«Qc³_ eؘ²áRr…Õ:ÌÖvv‹M©X…ò¡ž©äRGKÑ ˆ‰à½Séš I"°`mÞk!ádÐG{OÏÖÊF&ž3#̱ WÁ¨´&ž·3ö¥ùìì!r+ž°³Çé M,…t®ÊFSÑéà˜“Z7ø®"˜ªï<ü Sq·l*×A ÓŽšS(ƒÖþY5i–+Ž`P‚ŽDÈGæý4ˆ†á J0Õ.ÛÆÐSÑcñ(Ô:ILgØàZ!µ¢„®ˆ²ñdÈé˜f•À©.OyŽ4×^]n蛚‚™fÆL Ô%ÂYio6õ 壯c‚'"ó—‚¶¼ c\lz줢R¥CZ|„û3òŒÁÇÎcP!\àQE£ßÜ¿÷^¸•Ìž†‡xد…Ê|ds…‚ÐIǹœˆã¥ âìiÚl£C§rŽNKU óní[9¬=Ž/ÿâëÁÜåUuZ{f†íŽÛÿÐØ §¹á—¦1pŸN‘€ß,Ú†øñòÀzìÔï§­¥@z‚ô½X‚(½ a×-ÏA‘Ø çOx„ äN§Œ\ÆêX8HÓXZ4ËXgŒìË^%棷&Q†;zƒÒ9£I/´;ïè]ÓtÇ'\cßàÄcÌ~¡C –AYù ëØCX2£3ús[²’=@Œ/Жvb‚r±ºžÜO}g;šWùk†øœP¸z$ò‘ƒç™­}j.rÑ㚺œ|ëÖ:F0Žã‘ë-ÍJ´‚-•Q0ØÃ¶N'Ðlg«B!%\ï/ØDùê6×´xû•è2˜Î Ù|Vù°QqLØÏ((490bÈ›¨XŠ)ŸMFyz¥”ÁÁP¯E¥‡*r’S¡.6Ó–,\"ˆ+r¨¤»e϶†¼·œ^Vfôôo«¨(ŒÕ›ÛóÏJq€­6’»’ÐL1Än PÒ"<ˇO8Áä"³—)>£Ú-NQä䨷‰dämQ»"È %È$Ntx`_õµVbZÙ…Ñz$E‚d ÌÈå$1XëŠg_ðk<tÒv×Ëëóáw/„'-\޼¢ÒÈÿtôZ4”Å´dUv’éqy ½9^¸ÆÎѬë‹t=Å?ʬmô§”ÌC%ëvøF¡ÎoÌ0øž—ö“^^wÛäŒW„Ì×FrÛ»dÝüJè¨?{„Bå žM[vòìñþ«<äëT ÃÞá³?Ãç>HHr=RäHY[¶déÉÍY¸òK?û¼&X°pÖ‚…ógÌZ´hþÂ"6†ôÌÆ…³f45ž:«ÍSûÊ‚¡}aúµ‡ISÞkV5oý˜M`EX\ÌùC¼ª¨U,©ìtíí5+@sçß>Ѻ;ÿ;ÑM»¾P¨Sä2²èÂ}Q›W릆'X1rH ì‰I¬4N:46ð=ßÂ<šY·è\„Zã/Ri ùЋ“2ö>ª\hˆXæ'}‚*æÁ”Ü°Ž¿‘îÓc\'Îu Ôa9ï?ôuV$×Ì.`-²m¸šþ—bõ¼½JÂ1,˜£v´ª]°èó^×J}3ÒÙ ŠVÒ¤ ÑY‰÷CkW5(•rí°ÐH‚yÏGv®Õ{)ê*”ëRLj@u 5û%ì¥Þ| FØJSgé€bæUŸ!pÂY¼Œ@f 9ím]iÔ̰dÜ¡M æ%*=4F@ø–AÓÓNb® £‘é*qA1æg€>0oûÕD¥"ªø',°q¯«ÇEŠ%r‘½f)m5Ùk%Åk±ìZV–óv£c&ìÿ1iÔ3*RWGEjæñЈÑÚùjå£6¹SÁ2'ñ«¡­ €Ñie{Š*}aÄö„¡©Â®êtVÇAnuªÕŽÙc„kßËtÃXÕ ¤`‡Ò?vß!_#‘ñÎÎX4î`¦ h÷¨Ì›b'¨[s3©2êsüî"SòÈïŸVîÐïVIÔåoÐÎïŸÏH‚­òöÏÆÊžó –P¤`tÆWÃcõ¶›s.´è´;`†ÏúëºÊ#®W#tHD ƒa=‡¿6’ÚÝyX.²îj]«Ñ¤k(¬Ì×Þ¥Tš5?W©4F4D•l++olY¢´ä™ŒŒ0µxíº’ ?h]’.~ñöáÿ„9þ´#€rïå1¢!ðƒèÌ.±ÕÉÓÑZÁ|Zd«»­l–µE3TT/}}:›ð5}á‰qîq³ˆ/a{Ñ|"‘O¬ÔÓV ­ÔZŽ)÷Ïìd䎚JEÔt`–óQ^«iD’}¡M§qd©«kr¡g ×íc;47ÀÔMñ8€»d—MKûzü¬ 4Œ±leÊ5›U2öÞäòˆNºÔç:ž|®‹²øk72Ú€šûâÏÅì—&Y• Ääßüá©Ñ}’½ìQ<„]‚EÀ¯r!Oýá·×i/‡‘¾V˜ù,jRHAH¥»Y˜ ×JÐD®P bиëÇ`è{« çÐØ˜ t`"*¡”åYÁýª¿dªD®ž„…àÎZÖm¤¾M¿•jk©¥õ%Ö¨y'ájáˆnÖrA,ex¾ÐṼS-ªâŽ›ßañ®ÿêÕ¤¥ëPÚ±IÔ«}þP§ŽméˆÏž.PÎ#¿ô«;{}Åžÿ‡q°¾°€SòK,Wu-’“îú¦ÖµÜíU¶߸kAÊÒsø}"9‹ô-þ§ÿ‚s¶@®ÜÿºÙñö,C§aߘ‚yEsÊe¼nB&úÎÛg¢_ûêÿ`¢×'©rí”MÈý|asGo¬°¸ŸOHÓL+͇¯9XùUñ·,]`OÔæŒÚÊ8*Rn¶E,b«Þ LïöÿÐfØá$ÚÔs9ïw…e ‰ã U'hO7mjÒæãÙtMUåŸÓ<ɇg>ÄÖe€ó2XíMkS_¢¶%¾a'Nh¯/yüž¸ë·ZÞËÂÒ'nhçîÉøÔ}âç@^tJJ¥h&y±#XVv†0äæ#‰!Ž'ÏJ=0ÿî¼¹1YñsN‹3QÇMˆ¸tŠÚ*ñ‰Ò²a¨pÀ»çñ&ínÕ°5Ó~ø`A{¡ë3«=Éë±Æ¤ÔRè`­`àPÂs¡i*1ç[5¯Ô& $šRa‹Â+â®Á@‹fI÷ÆÙðŠ«TŸuViµ>êýW© p¼™ mHTÉ's[:J”±‘ Â9˜,¨Ÿu9i7fæi¹Ê~°À¯=¨)Z§”øÕÏÙaé)œ»“ûG,17cN´j#fUpÝ:jž‹ˆÒÎ+Fåá'ÏšYa¹L¤¬‰•oqØÐ9NŒë" ·ÂQÿíÙr3ƒŽ–œØ8g¦ýbº…7s>ìøØ^¼MhßïÜìæ à9¥¤r*é…=ªHQEòcrá /*d>®B¿¾ {&­Œø¨K—_à Ìœ¯áÇ’“xÁܱ Çʦ³íÓ1ÒÜ“h]AV0癋Ño°«)úç>ÈKÂÈÂUŸ°É¤´°‚.Ì&¸Ë ãÙüOTØø¢;uU…þñ™•Âß‹Xàˆ<2Uc¡gÔºº;ᾩ¢\12pÑÐhQÈšÇ+0D–ï„¿Ãgµ åºL‰GOeªS)CRwDÛ³&©S*ªåWeSŠg0ô‡¥ •m¢f°éj¹× &{6£?ÀEXÖìLcË&£\¿V*çòð+Ae>õ²-‚·f¨Xam/Ê«¶Â7¡?€¢i¸¸ä £ÒX€…À󃱪Ù$°‹&ÌÐ}¶.¼Ãá6C|кú7NöB OS”`U—ÑÚ>èä‚fï§ç™†0-°duSlÈ鬙(ût©5èX¿\™â%/XÛb¢‹çì‡Ý§7¸ Bˆ'šÚY¹©é ýpM<“%g¢Ï 9ãã5~¹=FÜ­R_^OA´T¢»E ¡ãŠF#zü°/Ùy03Ù™ÇnHvù¨YP43Õ\̲‰ó¡ \ªYþM”OÓÛsª&zpjQÜÒU02§¸M.2îFÉĨ…wY^Ò3Å6¯Ðœ­¼Dc#tÍ9‹Ì»¤ÔÀj¥Y¡• š³¨_Ôx˜÷D ÖZ7~áÂE)˜°ßl1Û‚ª…”ýãeöžòRw¡)`7wYó,\ñÎF®þñ¯D½1Z;•>ÆY_¨UÝò+º‰# æ¥Ðè|øçÏ96Øáü”–Ô¸˜ªö+)ðR 5à"úùs%l‚{«)YEs€NX7Îà1xVw1ÄãÀÝ0wSèÂ&‚yU(yÕÐ#~ýJ¡®_`æ0ôóµå< DGÐÎÏLD¦ØÌ¡×e a4w¹±l4%]êVzUÁ ¬:•ii£R¹TGn¾F ³oÝÉà.E^Uò¸I<®úË´¨"SÒ©L7ôäF½Ùj‡µÑÄ?·†5®9ùkËi\¡Ë£¹ÊåfaÞ}–&› $ÙÜcâp7Ã}Hú5­ †-ªŠ,¥ËÉG.ÙOü ÅäÔÌŽgÑX“¦Ù¡jϺ’pŠØŠÖbšº:êr;Föhê(AåK)…îŠ*¼M[U„þÒE”ÓwWTPJŠ”fúx¦€fŠòu=›„»*®R:ЉËâèË-‰j'ÿRˆE«íŸÓö/-üé¾”Yâáü´ý‰ÃŸõà²%5ü)jeÊ>¯o”Í5 Ú’žµß±B…-ËÖ;³Tb.Û² Ðyª®oÌèMžH¿/C33£—3éz›¢˜m©¬å—èW+æAþÎ>ø‰Bé~'ÖåBt66M0gÒPŠÐ±M›É¤iº óŒD×!Ý <•³Bê3Ó~FõàIõÊDœw\ÔÍMP„¤8§sDúÂç5ªÃûf,|—xŸ•–Šv±˜¹Ð´K†qœ ^+N¢M[ߪ½Ó±>Ñàe*TÅ>-]èˆ]<º: ¼ù€xèÄÐPóV»ˆ8+•ˆuûHbD$ÌØÍÁp[´²TyˇÛ¦ž„ö‹Êx^#'^—c¨7…k°y,?M—¸2å÷\Q ú+ÙN±Ùwý“¸ÏævïÛX¨•ÊÐúpvê."±CÂEØé¦0VŠC`ú_ƒD¸®@›ÑÅË*À%úö'dÓQ€Ö‰2¹I‚L…|Ž› ˜ZÄÚ‘œhœH³q·ƒ»#”¨?’²¤gÊ+8bû¼‚…Kþ¯àز<dž‘mÒ¼eüd¾…’.³€á5Û‹jç`ñ,;ß’¶€`m¯Ð?OÚŵăeëú"ó÷››r3Œ:aÌŠ¤BÖùÓu)/LF?ê—ŠNcÍdÝn—8-íÆm°^ÇìÊÙìz{‰gR~ iXàé|xÜhmk_(ë´1­æ’ÊŒàQ%ºÅPeÊÇUc£!n­ŽK™bý‡øŒGöM¢œsÃn XÓo¹îN„•J“D+-ýg•÷Ã/7Jvê²øò(å $}n:kC©’Néj´噤1.,²Ô”j´~¬Õ;r{ 9ЙyÏ0âXô»†‰:Ið°Vˆ·lø•ªg?"£‚åè€ï?à“¤va•*&ÜØ\L°ÁÌ¡".ľð_/SÜD·ˆ'*RŽÕá,È4Ö[•Ú"'£J9Ax¸óØ76%¨M¸$ÝÑh¡Øuâ4ìµLUÙ'NmêVkG¼HŒð2¤•uÄb )lWDöÞ÷ÙçrÙ*0©ˆÛq§PôüÑ~z)Ø× bEsAg^pÕû£°˜Eââ”Çlï*õßa–,ÜûS]<‰© •N¥@=F£ítúÔŠu³:…CÓé/ðcFÔÂ&~ÂÊyN6]Ó>騹ÝiÔ!OŽñeB˜BK` ÅNonëÉ1ôÔ öwä”ý^É Èñ¢Ý3 ¯¢yèÎ1ïi\ þŒ¹¹Ð¯Z£„zòïþÚKÐxFYŒ §Ôß`í`KbÕ)]}¡—ÿÈ“Õ(¸ª«DNe‚W|t:~«X fcçrùâžÅÂt!ݬ^ÃùPáoÏV&2s™ ŽMm´º”öÄ1v‰ôq“¥3ö¨êIÂð‚…†X˜Œ!µ¨²ËR3iŸÎxT·›^£³øã&nZê\ÞÓ_¡;L£:qŒ& ¹¾éMւÛwVm[n×Q›VßDQ)r|ŠŽ¶‘M(Nkª›5`#ú²i]ÿv/˜=ý{þí Bc5/ÕIçËr‘–)Ø1GÝ‚Ó(ÐÉä¹WLâÑø®­HWCTÇŽxÆæ[ÍÅ~T+€/r†6N¥M2ý¾~,‚oàåLÚ†|åéÃ/–BwÑ”OEI«¡GÁh1Ã~Ño`:&‰¬-%Œíé8'Ó©©Œô¢Ö·Vb+Kj™ÒD‹,bMöªÙmbn5!=Šž-èÀÓµ~Â[<—#q\\4v*l…|ÅÕ3Åm?rÍ!TpŒ Ó¦Öµë°'‹qµÕ>O›=G'ë³R¡ zÁ˜]ؼDù‰DÏë€ý®vU< ÈÓ‘>f²^ŽÔ’Dzn¥FÅ¡7Ü÷š1I¯ÒsA{g‹X´[Ô`V`È;àéHÅäRâïÈqÕúNBê,E~³Ñx§°³ò‘ï]3HguÖä#ÏÜÝAŽ|} µoà.Óž ~F¥#cétŠ kÆ¿Óêt±G`’s8‰ ú22a\UF ½" #ÐÉ¡36M$n,áB“!¼*iúò‘áS8¿ø«ërÃÖ­šN¡0îp—’ ¦žÇ]%1d\Ð"v¢1Pž2 d¯cÿÊbàÌ{]ðÂ%’a½‘S~»Œ=-ÿ®Œ%­Â î¬.‡w6*ôg67äÂñùÉX-^[P¼iUâ­°M­èDÌ~¦RžWRrÒ)­|e[aõ^’r0w.ꈕÜ貤 ¦š¥qêZ§.7tè>Mh¿ò ÛЪŽTB‹ÑÄK-ÍÀEˆeÆj°N(¦V]/ÞØ¿ãÜ=_µî{·ôït‹·+'ô^;å>”y¹Ýæ¼ø ÊöÝgSÌ ã˜1®rŽnx¸×q)CÂ]ëŽMS‚6ë•ásAC MZkÑ6 ŒäØ´•…¿>- h*ÝÛ¿Ó…=”¯62ú.‚½,6i$¾´´F$òHM7~\onç‚=?|k^ãÉ)£~¼}M8½XÓ:åu^ñp/*Ðø.7ÛÕå£ZLþ:[j—ísºüú‡ÿƒÓe\‘ÓUIz}‚S…¿Kij¼!°†}TB¿Ýíñ…ù€¸†`ư,…ç:ùÈNï`¹DŠ]¥ÒЋØÛ°Z/ÿ!L~‘?®z"I4)ÊU2VOz½èŒ\Ï8ꛉÏ%õÔTö<‰ êž+®&QÊÂ5:ˆ+—4uP¿¯ÇüÓ8íj¦Úƒòà~ï›÷Ú%/pcêJ8~7tL]enèYé¥\£4ë:4i'Œ];þ¸'dgC<ʧp™žÀ*·Çrs‘áëôw2A7ÞVcœå"ûÄìÁ ¼»s‘GŸ´öuáåûjS&þK*´¬çà Չ+ãĉui§iŠE¡E¦ÜUYÙ¹s,Á?‰+äÞù¿&Î|øü_KAç¸kàyä ê’¬_$tËE~õöШ:”œVa&T…¨á$Úͱi¹HÃ,ùÐÿ±¤§xÖM2»q¶??zø&â_Ɖ,;·6éô‹!M¬ZI{Ç'7»ä„ Ó×HYt+ÅòJF©Aì0sJ•}òy„hã}—”I½u§ ežv…| ,ÜÎÁq‰ _è·À¬pÙU¤Þ…DX ô¶Ͱ0ïÞã¶šEZv‡J¶KKaAŠ»QÝ*÷æY5Â5µåE1ù°*K(ÕΟ]ey@ýFGèï ÀãÁV!ó„â´=ÃêÄöƒÌ„qbëMí‘àh5H‡k±u5q]¥VqyÝ;Α–ÑcئVœ“C)Øïó†&‘®ÑšJŒôd9è¹ÑD '×9žÔŠá:éáä÷Lͯä:þ,¦Š1ñØõ)µ«èÒÜò¢ù(®ò¡-8ó¸gl=Ëؘê{ûFlùü5al¯ÿé…íà·øËd:?‰þ3v\¯¿L×#냧e KAhf»8>„Jñw8˜eØèuJI€âñ'︱Œ[ކ½òRlˆê\P4'»Ã•ñ Æk’}áiu¥¥\an0-½U Mã³c0±å'$ññcLj‘JˬŠâA‚‡À–ækga¶%NÆÕÒè©>펢¶Ã7Œ ËšáÉ9±•ÝèVX£ý+º€|ÀKyÍ[ ¸$¶]ªß¹Œ3dNJóŽ8Ÿ‹Í鎜’vé>¬?•Z8ä(ë¢b@åìÒ´…×8vpõ.âÓ Ò[.T#Åkrá ± É@]2å40ÅÞÃjÏÿ{zÂqI¡ŽQ¶‚¼kìixºÊÞº}iÏރ؟ËZ«½òÊ×3ïi¶?Ý7.5@b7Q¯3¡h´ñ‹ûŠ}‚p\‰îþv¶Üýcbóºæ¨7΄,¯àl¬Èp¶¿w¼³¾>óH4PãXNÙͶ·c¥.Üd— €Ê §ø¦ö”va*ù à ùð´»•*±ŽU ¢Ÿ*ƒAžv7LþzíÍ:{}Sm¤Û òˆ|,‹û2tú_Ò— n]v,åæ®@8¾ýåœ)õøšÌ•«ŒÔ¬|胳¢i‰!ú1r ù…lë;ˆ^DÚ†LÙ§"„t@Õבò•ä#î{$8 óc2ˆŠF‡¼jPéCªG¹7HzýŠÕ¸cq‚E˜íŒYF¦²¿ÈÞÈ^Ÿ˜ StKÚIrm1'A>ôæß˜§H›µŠ- ¯ÕoìË,)5pqÐÛuf¦õùÂæK‰_TpÑÕÃz«{6_ÇJÇìxšì´;žL¦`(`Ê|çÿ±U $d €§Š“m1Æ›j3Žd&ÎIJ qÔ.îõ»:eS²ôJQ}] Jn9™A{}Ó’çà1°k€¬ó a ¿¿AÝ&óÈ ëSvõ¬ak¤£”&›f4ücæéR_døA¶—غƒ—fL¹*´¶ÕZF;ZRÀúŸU±KûòÅ'¥ÆFp†!šíœ-zõ×x]uÞøc&, ¨O»]눞Ë@]7¢Öˆ%ƒ©.: ‡Ë¥cÑdRúQ×Ê𱿮 $ŒŽ—Sš4L¡þ2¦l&>Ò͇]«]'°ÙNwíŽ ¼‡Î:ò1YE(…ŒDbt¶ÆfØÙ¢ TåCórá•$.(3 çÜŽù— ´Ž5˜…“»Q16„Å×j¤;Òzª©Š ?ŠNÐæûw|Ýx#â'Y¬)š1Q¥‹O–i/qês‹”3ËFN‡.º–,É0Ú,™¶ð¢{ep”Ý2¢Us_h‘Çu££1B²j–Ô|üàLÑ•âåvþà^ž±ÊËÃpŽcç’ŒîH]ñp¯€¦ð$S»é:b”㆒=2+›Öb¦9‚Àv: ë"ñ7rýu*DùÚ,Ñ{=úzxÇ{¸×†ŽüìnD]¡ÃËe2Í/iÑ{š)¢M‚ß+™¸ýOˆƒ"!\dic]á¼ v¼pGd{xú´±è5Z¼|Yþ&.œÄ®¸9Ñÿ-@?z‡¥áM”UÖÛ¿Ó÷të8í<ƒ·[;×V€uéOš-j1Š~V•¸ŒÒ×ñsyTE³´†Ñ¬' dòîÆÓ§ÑÃQÓ€žHŽt•FDK,ÝnÿƒQÍ ¥^’é¶0¯ÌöÎj‡Ø®Ûç{n÷ÿÁ!6¾…Ú§Èš|øÐ^‡ê6Ë䄲˜ŽâOzqZ% °\Bë´áQj´›«j¿Õ²p‚â ¿k¢dz°ö¥,ˆ>.>&CËòBôÄôl·dÇxå(Öæ\ïDW2‡x²3 kg+ qž´>‰0 HVPè¹q3("•Ù`ÔR‚3qâHï)ö)gˆ#çH³øßŠ@õŸ~ÇxB–Üg`:,S‹<š"¥®héÊ{©&Ñá`bem´8ð¿¨Gg‹+ Sê$#ë`ŸS­V-bÔ€á#öÕ?UÅY…8¬RlpY^dø75¬†#}znÀÎýMƒ¨Á,¯¤M˜uÕäõ©Ì ˬG÷ÿ­]uþÄ õËü&Œ(¿HÍ|è³÷U}ç­È´Q„¼<´ŠFiƒJ%ù=‚í*Y—ÖuÌ ŽC@n¹¡7¬jLºøˆ|øþ)¤â4‚ƒÓb—9D …$FY Ø>@b9VDxæn+x”›N1-ä‘ÐDbE>˜kgtsർVºòy Þ?ã6m°6 ú/7;B¶låVq<ÓÂZ ±IØWô¼\QeRºš1(+—»•˜E7þj²LJ:‹OÓO´íP5x¥ є·‘T”PlkÓI‘˜켬d\Á¸Æ’­ Å·¦S®kz•ýHRfi Ì#2ÍBÓ¨°²·HÒ»Z>®µáY=ðÄ ²…1ã Aò´ é‹VàžüF¢‘ÊB Ý^D/à ÎÒ[Î2EíÍéÌH†ƒê ®Ä¾ðûEÌçNƒÉ\¿7=:Å)$HO‰h;‚X¹HƒÞ òº)0t€6Ý1{/oÀMÁ¬ Ä9ŒHªütÊ©M„{ÐDX…ºX‘v’Ó¬Ã8·×_Ö˜1ff–4Ì·»Mˬî0'7L ' IbYx¤Ùªd»)™5óž·f—•F)I-ç(\³šÛO§®`âå'S™LG_¤QGÊ[%Nk‡3à *R%o›×NÀgì´O Iº–}-²ÊúÅ ŒêßËS`>çu’’†ŽÔ2$ ™“, '(¤¥Ày(§Ï×hGñ`°Õ¬Š'FvˆJ˜€+ Ø 0ßÃR¨¿ 4¾×OoàJKvúó—–â+¬îÅ^¨Fr¾Ø~¨éä|)ã‚úG}ù°MÐe3Ȳê¹u¹a—6"ôMïŽYa_üv§³‚ËDÝlö~mýÛA‚Ä[»Iï‚…ŒBÒöÞ¡ØY§= ž±7s½•q§œx‚yðŽÚE¤œX°:ˆæ]‰.‹ C;üš`Ť*Ú*Â1WñÊÚJ÷ÓþÒÄF*ÇBÊ/ÚÊI4KMÃæsÝFãoÓ‰Â*ZðÖj…™%-ejXJF\4ï¢r*´ ȱ*€öÆ.oËQ€ßêÖz•7,ŸÃrëÑÞ÷9æÐétà %[ŠÌ+îò¬Òåô` ‰4@Ž=.^¬;_ÊwéØT¸î- s‘Ñ×Ú,'4èœN“ÿ*f"†…eóô92•+$NȽå#,ŽGœ ¹4(¾ 2À…=E¼Ü­b‡*DŒiY+ŽÓ¬Av†Yº~æhÜYÊ_Wlê:á¼iÖi¹ðŠI‚<—ìMô:ÅhJrë/†.íDAB˜ÔA9q&'ÎDŒ2÷Mõl#–øp)¢êùeB×_Óžw­]ìñÊx¹›êê@‘;ß!ZÍË@£Pãž@ ‚ˆ„ž“2¥ˆä&‡½"«£X‚¯# jòV¹´NÌ%è‰ê\$t‹ét ;I^â¤(‚³—óbMœ¨¼X ð5Çï•¡ÔîYÓ½‚t²âZƒá™~_i%‚»ÊJ¤yRŒ”ʦAÿ¤ÚòZ°ØøÆêÌv@RõVÅc:Tø‡=`Ê9⥉ám©6Ð]Þ:‹Iª°F•ZlçdÙu®kRv$?ôÙU ÏI²cQ‹\CjLÞm'?)›þ½\·A¸—i¹H“èª^žým8&ë)t&g.‘Ðw qëë%)Œ¯wù2¿0‡`cÆøNéRE` 4Öâq ƒùו³R F:–ô[M*úõRÎÆ3Ž›©ŒÅLËeŸ@w_1Ö AÓ\yºñ’vÅ©ˆ™úRŒN¡­@6qj{2±þ-Å Ä|]<“ÌùYñÚBÍ÷/׫ µŒJæ¡)ªdœ Œ…Þ¿ØZ¾Ê#ªA}¦¬xx‡¿H¨ƒ½æV0^jd[|…´ÀÅH;‰ý2tWüVU³~lÐ5)>žÝ¶ÏÇóVåÿàã™PêãA~¢M`×CMl]·É¢™/Ñ£á2·5M%(Òž–Lžc¼9<›¡u÷c-ãðNш#•íÂ{*ÌZHTÍôyÞÝPxÂ’NµøLY¥œQÃlŒŸ¯9ôtæl m1ÌeÓÔ&— Õ¢+H}R.•ÿ› ŸrIKΜòe;Ðô}ðƒàD$ú«Ì`ñb 0£Í”pÒíXÞȼ5•ñtJëèÊJʇ‡ÕQ"áZÉQÏdiãÖñjÆ÷Ñ3eŸ€ÝzI Ú: l=©,ÞÉu¸Œ€ªÜ v*äçn«_EÖYo keÓpóݘÊ^s-m¡àè=EŸà©À•#‘ kðT³ß_Õ>1nW…«Î".7GÜPËÎá:5x¾tå&f+üd1…•.d÷;hÒ1;„H[µ…ÞÀ!•|øéýíªŒq߇yžÀ¹'¹µvzF\Á«QDaÆ—ò³°€Ô(UB…õEnßÝñÿC˜¬$h5ž’‰>@™*\x# åR¢%Ï n‘Þœ:˜!-C2»ÚEÃÀŒ[¤°:Gh  JüÕõn¬øÝÕ§öô¿´ëäú§ÿOö1ÓvÅ?¶’¹ï½©l Õ ƒ+üÓ³¾â¹æáýßýÏK ZÚ¢‡OÞ³'÷â¯ÿyõÖ'ßrÁkó¯3•q³ªsËtÓ »ßÔÿJlßtè·2=¹+*à¦Zø5wòªúï_y3ÿ~é=,M7áââSg¼wRñ©–;¿Vtj}Å£û/°ÎÝr žH?Qrî™'f—œ{éð‡Jν~Þ±%çþñÔÏJν_;¶äܾ}kñ¹!¡—ªJÎ Ÿx]ɹÝ/?¸äܾo^UrîÐoìUrn¤yɹºw†—œ›Øøí’sÇ][Qrnæ§kJÎÍYøaɹE7ŸSrniø%çZšÛKÎÅï~¥ètà•‡ý»ÿ¶ŸyqÅ×”Ï>uÃ×.®Øã£Óé,ž[\‰ç¦Ífî´eð£t±Šµ©æþƒ~ótÏÅðo<ÓÓÿÎ~ûôæÎ»v½>Õ{u[L_ó¼§ÿÞç¦Â“ÒÿìbÎN\(ʘݟV¿nã¶µïŽùŸÞ÷æâð¨øbÅ Sb3òÛ®~~Onþ¿v~oè%á¾3*†ÂR*i5î¨3—,>½Ñ::ãW߱ޖ~Ä:Šõ…­£Ã¬£®s.°Ž²/þÒ:ZsÂÌÑúŠ ïšl^rð*ûðÒïÝc®{ÿ=û0¿¼Þ>ì{"e^3ñVûð†kÞ²oÙ¥Ú>¼su»}xï«?¶ïŸ÷ª}øÐ}‡Ù‡[Ž<Ë>ܺîGöáïþó‚}ølû~öá‹¿_‡·¹_ ÓŽõxȱ9Öc"ÇzTäX‹ë‘‘c=6r¬G‡­ñQ'ô©zŒÔ =Jê„'uB”:¡ÇJУ¥NèñR'ôˆ©zÌÔ =jê„7uBœ:¡ÇNУ§NèñS'ôª%ÆGýŸ~owûðƒƒþ`¾]¸Â>üû KìÃ×^ÜÏ>|¹ëûðCd>µá,ûp`ôaöác¿jþê´Û‡ü³Ý>üùEÕöáÝû¼eÞvó­öáMßHÙ‡×=]o^Ï>ô¿¸Ç>ô¼UöaoÕdûð»÷ÿÇ>üÖ)¿ ,Œµo\8^½¦¡táèã¢uFãbãÀØÇ82ö1}ŒccãàØÇ8:ö1}ŒãcãÙÇ8Bö1‘}Œcdã ÙÇ8Jö1“}Œãdã@ÙÇ8Rö1•}Œceã`ÙÇ8Z¹†Ã8ãU"ù]üæã°aR±´ÀþÁ+ØE‚û¨Ã”/íe6\|éù'ËÅÙ¤0÷S0¥SÞÕÕ¶7ì—§‡Ÿ/±äy´¯¯x댡6þµØýoÀ¥rÛ–ý>ÀÛ^«:n;a³rßw½ÚsÞ‹S H1AJ•Ÿ½þ*ø¹µþÒR(*^ªx:åŸþCÉî_Z·¯ÇN‘\°7³Ø>È0ô£èì/5ð™GHYQ•ñvTe³¿¢n:ªgý¥8Jq8Á3XåY!ƒ3Íð@…H&k͸-\j™´dÄJõýÔ&r! ƒmÊÓÈn¼fÐ˜Š¸ݤ¦•B ·S>|U¶aÙü7K6®+Ñcn+F«hu]nèq ›®¦XvÿUòHw÷E¢+°‡å%÷¥ ÆüÜŒÄÿTŠ1&´p‘«ÎºÜý;6&}øì³… Ü”ƒW~Q¦íÎGæ_Ëa¿`©X¤1tWÔä"½˜7-P ÌxèŤÖA!ÔR¨d²Ióá—ÚÈDÕŠ7°‰©Q´ƒžÌÖu%§—Ь¦8C·§Ø1¨‘ '%·ÂµËç¥Y“ ï•rTÖ¤TÖÅÀ+´,a9faaäãÔû9JE @%a(*EÁüB]ÐIIši‚û¢N5¾¼nŠ5 èÒêÐiâi p>´é@ú–‘ÐRëùÊõF%0‘.Ñeü¶âTIÒÅ’òö#Éõè¦êF±ùh=-˜¨€¾;U`E í¡'?ÿàЕÈMò™|ä䬑‘nàQU=šCñÀ“>¥òXß]iØ|ûeu.P2ë…éê´©  Ôÿùuý ,x°ç°› Õ ¨:ù®N-`ÓùFÛàèL¸\¡3a´Ï8B 1îƒ ÷{á$îr&©*äRÉ%\$×0îî„•{l3¹ßÛ÷ðßµ­«Øl2üÿÐÖÎL|ÒÃ5ùð-¤j¼tÏÁ‹D5vDÇWŒßn÷º§±"Þí•c k…‹u¡»S€ 7sÀ’£­±¨¢Epé¹M”ª¯轷ϳC¾>Ön_g|ÒCÞƒ]Y·ƒð„Øu8¯B.ÚE”¥n$%%si/e(2ÔB]à _»^ûP Þ৺\}Ý:øL¾qmÃ~?Áá[ÕùЊÐG&®¶¾/ʨYB_:ANPè¿ê1?¦Æ ÏCÖ凜} ¢ÌJåàbÖ.®¢7º÷dÊÃîÀoÀFSmd2'ün¯@f;í}t˜Q¬å øL/ªÐ¹¿н×:©,wbÛG€è A¬©4%ddR 8e~cè¤T<ëz+×}ç@'‘ÕÉf¯£å¿ã…;Ò„>þ d!¸WÆú!ÐBÖœö ] ëbÆ^€'N:gX ˆè¤Ú-¥BªÊôâ¶Ñ¾êâ4yš#kÿ¦¦+òÝïB]Rù¡¸÷ ¥¼YP ¸±6ÕV+óCž¯?Jæ nئñã8ºôPÚù¾ÿ€“ø!œœÊҬʇÞj­SvYü3*ŸÚL« 7;̾-kĆ5Ø9x>mâ4˜kî÷ꢶ¤ðØûðæ‹`˜ŸB€”€ËRŒB ÈsUå–F¤uzßUo6ÑÉLÄÚ¹ð] æ—– àôV@ŽÐ ß´^®âú™Â4ýñJª-_úPüÁe#= ?ÃA>Ž«q2ª à6Qp†»cn<[í¥§ã0V÷àÂ@«€Â`_Û¾0ØçÃþ‡0ØD»óÕÞžþ¹ÂÖ{Xa+W¿qx2†Ps¬YfªiÑvϼÜ.//‡nÅ_m©ÝÔÖƒ ºÞ×Ù8Ÿ —Ã)C‘|ÿꜽ¯íû“ÃÔéí«í3~é³úÙ¸Õí]õ§M`@P­'W :xQæOIÛgäv9‚n;|J$ѵi)±›•á9ôÙ+–µåG½½[q 2Ýœö‚h=ë$xý¢Ü.gÜ`^?#qŽy} oÍWUD®?+µ©-¢Ã¨PâÄ ¶I4ŽL¢yN§ 2©¼Ü"5'_ÿÁŠ'£™G,=G²JDS¢ÝÂT8o£„…üîNî'ñƒ‘ô²(™…".>âEÇΩ»¶1žAL.ÉÛE±nüÉØnëfA’`¥ZBø‰¨˜3ø¡|8ÙT´Û€»ÿa C5!•äЩ PU­Wû²iQSÅpm±|è|F%€™^*§ÀëŽ?/¥i/¼(c>*«Î)ŒÃvÉb¸·JbŒ,Öž{¤„_ö¤ÊýQÆK5bµÕã”ñjßEŠ!)QøIê4½Wg(­³dLæ9É‚¾°÷f«ÇWú訨x÷¹‚àúýZp4_N ³r¯$®Há7é… !—¶"ËZ¾}áóEUP¨¡:VL:¿~,ôí¿ö†¦ø#Tyáü2/ãúU†:Æç¬GøCè­L¸Mr•_á¹ð=íä¹(%¦âô´·ÒÄÐN•+¡.ú›)|ÝSªZA%KëP­„þUùmƒN(_êŠÖ³²‘"ÊìGÅÍ9?>JYŸH÷í‚}îš#A/A²QUØ»ÄAÒ÷ãÎ0ݬËD¸Ûù*ÔsáÕNŽ¾ðœ °ø»e2)tj¸>@¬F š"‚ÀI‰9‹D¦ Ï&*©X0³ßŒ ³B ‚U¬ü±ŠûœIü`}1viÕCZJPÛ³SçÚкê¼ú±c—‘1ŽìÖEkÜÚ¿¿‡ý¶´\9fS•ÊÓHЖå sP;`^Á$=AD;¡ÐÀ³«4E0× @‚3MuŠ`æLðeÃØŸ8ÈÀ¡º%òL©¥|t×_{[8W] ŸaÆ SÁl1‹£ëRñߨ$NŒÀ⎠0$h*!ÃÒœë°Þ>»Q3!d©~T+ÓIÄa{÷qUÿ!ÀÙðé 7ÔCÕ /žò”…\4ÔŃ‹|„EJÆaçm(¨Ÿo3~—æ`éå~L€pþá«+eŸõtkOÀÕ‚ˆ g–â®­Š{»LÄd¥l”â‘ ŸØBEÜ Э°îÈÂ"šÝZDÙ“¢HËÁ³¨Æ[má°å]¬d€Ií0çŒT´í„¹uàz]¥GƒšŠvI<ÅŠS*¹’^”é /¼fðMª˜¸"ž·Nòn°?ühLת(,&ˆ_KV¤¤ÃüŸ²ÞÿÅÝÍG>z¥,gxMnèò‹¹r<Þÿ–3£0þÕÓ¿­¢¢0jTon¯K&Ú Þd˜AXMtýÉiæúùО¯¢"D#"h#‚ž^ø'½*W±å İ×c†ÒW(ÒS ýÅKL™ÖXÑN|v±"3"u—š:+ÒêÐûw±¿ÀI˜J…dãÝôªª¹–ÈF¹¨Ñð˜é´R%aöôám6¯PŒA …Q‚زQó±óSmH¨Ô.ù@ ªæ›Ô!5wfǹvLäÓÝ3¥åÌÜå6]>&Ê…ÄxöD£R"^£b‰ˆO攂ñSÖòáÓïÀõ–‹œÿ\£xU]IÔü’n+CNj”&É©|Ø/|…ºŒ½ðŠ÷S ¹ð…Ï’æ=%ZR­ý€úóˆoAWiE2–Ô¹ÐÝ’^ØÆ¬õåaj´âr;Û…ß2ˆWκôÔhl|â`|øªëAJ‚,JåC^oSM¬³SÞgLCƒ»5Åôɸ³ì‘JÅ%‰`˜ša÷'¹áiDqdC€#Kf3-¢ä7š|9¦b§·U^ŸÉG¾9Á‚‰á}0ÌW]…±š\äʇ,ºM%~¢å@ÐÚ–Nžù¢:>{ì½NMinBTÄÚÔ3­Ë }QvÌ•ðV»Öeª5c¸”#¢¢úåk¤—…ÖeI.×pωGƒÔq] m·Bgmùðø»dø„)žÓã`ÅÄ4çJIT‰DÍ6O(R¹ºžBVIø™fq,ƒS#u_J.NÔtdÿÂ-§ÓFÕáe£Nœâ®\¶ˆ#Yì[?­Öò­£‚<äKú%í¤Ð‡®Ð»ò¨ØºC¸.îÍ7ßœ° ¼¿ÚÁ{¼‡•`ÿöÃDV¹?yzäŠËLÊÀ>¿\ø ¼1/…¼é±•W<Ü‹¡¶PÏA"#±à)•vñЧçSÊß~Î×Ϭ~0•ö‘àÔG“d’òÅ>–“Bö³v¸ÍT6úù˜Qz¯h(ㆠ¶rµ!:ë[DiКå”ÁT›õI~šx™fìRáÅ„®éžžé\¨ïî4t/'júB«öêòÄCÅç£<“~°Æ×¾ÞÏúBtœjurhÕÖé°ðN>–|ø]]Š.Z¼²–O·ãznJŽÊÄö(àÞ”ö¦ÂëtÏ>!ù ¥g§ô¡“<†) 0gÙ飧ñ ò4RÖ¸x!}™`TbQPèõüñž]ò{žƒ¡k€m»êCí=½iN$tžívLåƒe˜$&B@‡_ªf›·¼Çž{Ìxg\ø˜}nYwùE[=ðŸ=8g´Î…»ô‡xõ‡êëI{¯ÙAUc@úü™_ng¥·ø«¬òA¿Tž…^gº_Ë5Ü{8™M¬ëZ ÛL'ì&íwƒ#kÈzGF‹¨@üqL)+ÄcéƒÂ(_"ËêØ´ª#¨Ü¹»o—7wȾ»üîÜcÊP¹Ú|A;ÜïaJ U}¤$,ÆLɮݪÂt,>õ\¬ŒÐ©xY©ðœ!uŽ\ ý˜}¸1Žnî$*f*`%ÆU"!â õI½2²ÚË¢²ó(ŸÆâ46o§)p¡’J&c’J&MXÖ{ÓžÓ2†I÷·æÍ·stT€öôéäkIÖŽ‘àzÍDD vX¿~‹[i»A‹½èï˜bW?q™IÄŠ¥uФ£É÷݃õŸðèëÿä÷âö:W*jÇ’ó0Ιv˜,D¥ùð1=¹©/ÞŠEkõ &]¯GßòÅÞû$ŒØ)=uómt¡zM¦žÏ㓸=¹¿y+>h,ü«º€ïîÉ]®ÜŠeûÆ–¿£ôõãðõ¹ƒF|ÙëÇäªñÖU"ºæV°q>ôþO$Nª;ôUniîÆÏ Rµê7ñÂmFâåLG¥åúFæ:}¡Bs|×öêbî…ç§ G)O+ný*Žûh€ÏóSI$Ä@$¡Ç‰‹Á’Ü]¦ÏâaÀ³ßL¥ìRÛÁ·•õÇ$6+ M…CË+mLO.rû¦ð€ŒrÁˆ¶¨3sá·ÆsmQË!ƒ /,CÊv\+DïKqµ8&ö>_ɉœsQ‘–êµÑò±=RLÌEn)Ð7õ Åˆ­à²¶ëDé«ìˇ¿õqœ©H°UŒ?PÒ>¿“%70¡¤"Ž„Ï¾üX›ÇŒ©_f1+ˆìÁŽ›çÆh´P2EáE à$ÚÆ¢à—&®nuÊ›óŠRŠâI³fñ»0™ãœÍÓ^8½¼r p&fxÄ>>âÉhª··oPÑT®'×k‚i›IÀhúl÷ë…)ÇQÚÈ%Gô¨ høž(»ìçxN ZnånJ8äcÂ_õmh5”»øÉd¡zr2tÅ ðÆT2¿× ŒÏ¬~ 0¢Ðůý ȉ5üFŨÈ/æj×¼ªø!\$8VLÀ°²€üÛïJrEáºQó<­Å2…… Çs¶=…å˜zW£d ¢æâ •ÇúÝÍòQX¬£^q+•`0/WÛ)„ä‚Î8†“®y†šbÂ=Œ¡WPO±h>ñsa³CV¬Ýfè~ƒu6äjTòÆ,ó0{P}(‘…‡tr9F©Ðf탳‡¢m^ÅI5­ îáHÑjôìrQÄðÙˆ¾þ&rø¤¹V[dÿ?“¿Sü.RBü.90,9MéÆÍ E[ο۔M!·çG½¢ÚŽteã…!>Ÿr±™·†|¼— 7H&;û¹üTZy³ã»Ô,¢$Dù˜€GÌÑë_QÏÖ©½–ïì¢ð›M -8òî—·Oh9ƒ<ôh-"ÒÕqÎú$i{üDMp>¹·o׋ÖÂ_õã˜Ðü' ?™T ÖÔ®s]÷´/üŸT›8tS-O²\2ºÕt’V=¯hóC“;SŠWš?ÕàÜp£ü¬zI1‹A‡ƒŠÝ†9Å¢} ß²'Ç ýlÇZ¸H-Ævñ/kD@›Âvőޫvr‚Ö” ´Da%\Ed•Z¸ |Ðpýº\Ú"%õÔÔwÒí04µ4è#t AJ½ìðÉ7‡™NT>‚¦mî }³‰<;.;HÄó©6¿>~Å:0è£ä Á¯å^¦3°Ëãâ°cY\†JWåñ"d×yqÐß’Ä,X½Y\z3érFÚ¿QšêèY‚gI다%£Õ“£)/†Å]ˆYÞc^yÐ[ãmüï±}Æí‹ÿƒñ?©ÈøÇ îl°‰y¬ ©µk$ÿÄjx{ÊÁ@nz äêm¶4럲1óˆùA#xLþþGä%H™ÊͨqùX]%rÈ?UÏÁBµu9l“·H1 |yµp.x–A¾™,oÂì§Ýߥd½ý‡íþ+]·vÕ­]Dín«,-2ÂìvŒä‘Æ.Ì&¼ÇÅŸ¨Êuc.¼ÛQô½B»˜Ž©Ø¥Àˆ|Ùô˜ÕaÕ¥ÈÂÖ{D3—tØ`?óˆ²HÅ"UËÜnAÚ?Zº’ƒ€nk.Tò=–¤ M´/¼y¯u„ËíÔß}Í!Œ•6ÜòKÈI ohº3¾ZÇôYÖí>‹­]Œ<ºTÄDQám§v(ò¨¡UU–y~÷YVxHïW›5^ç2TÞÁ†3§¾Áo‹­RZ¹ªúØŽ ÛÉ|èÁv§“ÆA³¯1zð§f[… Tø a¼Õ±hd„EWEPŒhš‚ŽÍ‰|hÞ(f0‡†ÐRà¸|EãSK¹xç†OÜ·&5MIT*µ×Íâé·A+o"àK+{U2 ÿEÝ,;cˆ ÓXb~̇ŸýT[M H>¾.H!œ¯Vî—6); ‚Ú ˆÎµò"²ƒ”©A¹ÇÈÙ¸çk(°ÕÃ`¢MU šÝslþäÃÝwflÊI|`u~P ­¤´îQ†õøVö‹šÁm³#kqWo{nß6qÜóÖ6¡dþ€â·¢3XŽÀ^1|loÿXuþÄÅhîævjZ£’•úÇËo9“-[ð²«#ÊE¤‡[:HDZþ¶ÊýŠ)¹P‰3·;E1ÌFeJÞŠ™P!¡)$j£bäõPñk£u¹̬š7} Þ­ÆC!Ù•>´µ3…l™[€9ùµQèÏ }ñgÅÒ{Xu.ÒôaS‘ü•XœàœTÒâÔÀ×á]bµ£+ØÐrö…þ¶DÁp²¡RÄ–¾ÜKöù V$éqJÁQŽ­Ëeà½cëíÌɘšÁRpDLÌ\œ˜Ÿœ¢TAÌÂDi±°I šÃùÐ;–&cªQ_!è*¬©©fbhHŒÛ(2Ö%º§ê€NëFƒàTÄé\Hm2éx¤%­G‹ö¥8^¬7rÅ žµ”l±D cÒ³R±WEn§ô^œ§,)žÜ%¶läãÏ=¥Ð€X0QãiÐõ$²â»äEMH’nœ)Ò)7yÐtÌp…G¸5‰%³È£òáìoÔÓTh5øŒ\ä£ÑgŠÊÆöxÍÒ§¨‘´wcź•9›,ëéø_‘”dÏóºD¦QTLÕ7öéûÙÌëÓð‡Bÿ×îëÑÜE=ý½|xo®aØ_ ‘f‚«é)ë+¶¼ypÿßíxqÅŽ‡þI‘!§œ»e…,~Ðÿ­þg} á­[ñIÌ¥uÕ†÷B®0v´ª~Ì­µt׿v ™»ö¾åcuW­4þîû×÷oýö8nNõ9”m|Õõ§”i<\m5~Ë~\\1ü™óìÆÃ9j|OÿÏ~¸'œ»®f)³%ˆ Âҥ袯E&ŠÛPW(¥v@æü_Oî‚dž‘°¤¨žý÷E#}Äæ÷J4* !_»öß¾Üp,¬¯¸üÊLFì1šd¡tgªëUIDë+žM¬®Ÿ,Êí^Û§ÜάøRÈXò,^Ô8ïrƒœ1ktéâO cÇ”‚8°Ù¥ èàªÝãÕ\`%ñ–[õ3ºé½‹]âÓûlˆÔ³3µÞÛœN$N-F$“Š¥’1Ôœš#0½™n\ÊÏ(u8MõªS¬P ¸S×ɳHʦ0ç‰Å¼ÑâPž±Ã‚ÔA+ÊÛ¹‡µ-¹x,9ÝRT ‰7}~¢Á"æÂîvçSaÓx'Õx¢·Sa§U ÃFS(„•=•5®ÂIúšD,j|6Ôèd¤Š¢ä´Êc".E¡„4” —†‰[”Aíb­Gqªh%Ï’°”‘òuϧ–”¤o裉R¼Aû.Òs®÷¦=»¿ôNg;Y’úU¨ß³†R¬ÜW[þö¾Ð_ü!qöƒ–Œ¯ööÏÜ.Ir4=Ï £â]²õ[ørmØ ýþ£M¥©?¤CÝU!¡ [2³9mÎÔN+‹$rXV[%­Ž Þ®k+5;7왑˜õ š‹]zR“ŠÄ X¤œ×µÌ7*X¬6G`¼&ÝŠ³VÆ£Y£‡Yý͉è„ >q Eñ*OgAIµ’Lß\s{*­¶Hƒ4†¹–l Ï­ôâdï*ªï¤ ¡ÔùÞdåtr·ŠTøÌ=ßþœÐ§\pøÁä ^G2§&yf¬Ã\@žh ŒõSXA''Šè2N®åË—ÕÂ$™¢xjv¹bi{I{Xëª{û¸úbã+ëmÚœF’N³ãˆµòä„~éX¢Tâõ§J²k˜Á Û’«èt6¥8ø<®\o©Ô>)r/¶ê'MÐÿlj,m"$0/Te~d@?'„\D2Žª#9ºµSæêgµÓ×ÈiwQ'"”Û¥{H›Þ¨Êöæ1ˆHzÓ഻ȹ—ŒjÍ\'…û.kG#›a‚þýµ±@Ù>XKToøU¬q3üˆëk­ÂZ'¨û‚¼Ç2p–ËØa.këGƬ9"áM»Vf9[M´|äÈ›Š•sûj˜¯§? |Op­ØB2 á„5ñ ä vú¬Œd‘Œ2•º»Ï`½ŒŽ‰)½ý,úI#…úé&ãÁ¹´î¶Ép-\ ÌúŠm×0¦%|_hDB»£ZìC“$¨ÝhÇ¥ ¼¨$åw;P*®”‹à2>+Oy`öQ׆õ…3±Lkl7 ò–†> pêUòëÇ?@U¢tJœÊê!ª*=6+>äVG}·Ê]ÖoS¶#Ëgëû¬Bg½ÖĬçð³â ç>ƒ¶uÛ[>ê0œöÉ´¥Ú‘ãêA$"µ¾[±I}qL˜|ÕÙ(®IR2[T`ÊÊÊ–a°€¯0AïºÅ¢ŒP#cAŠQ{ ꞈ&1’¦²¹Ñ9ˆoê"0‹ºbãÈàOüøC«Þ$|¾GF©Ïf­™k%î¸Ð¦ézö@—Ê\x?Œ\I~ÀcÒ pÓ×¹R¸qÆÕ‚e·H’B'}‚Ÿ’|œ-6—ìÜøq•ôu¾Öþ4Á¾úHŒ&ÐB]˜U‘E7Ê3ò„¡ú` ;¡+‚/u‹ 9Ãy{s‚CËu ‚¤×žB Þ#b1©–‹²*ሒ‚è¾N“ǃ ]ËV5i(C?Ve0µãLÉp×4.£F0ó‘Ô12y<¤âèØ:°Z†uošËŒTn#œT½]ŠèJTãHT—ñ)”íf?NÀ7¯@T)æÿÕïÁ²Ô'è'–¦âäàwâ´S¶véE  \ӘἼ´¥!\ÓHƒ`ûŽAy\|}:ªŸäRÿVPe å?–LgA‰}˜BÅÄÒéng5‰šÅQå]IµÑ|–}E^™=7-ûJ¯Œ×aTELm©ë:j[S`ŸÓn3ûû½òuc9>³Ò¹" }h"®6mr½äÃ;ÿd„²[°µR²+è¼ °±ñh›Öñ—cä#rú¤&²TÓ)ã<ç±*3uôBnräÁ‡««=ã†Uµµ•§EÊ3/@NQ^µØ•S¤‹š¶e­„ÀBëœhZL=Ei6)W=´¬’ôÒÁú­h€)ܘé2À¹ÍA¦û¸ÔDnãlì)*ú¶÷ö9(æýé¿tPÔkÅ™_±œeë‡òÁ“ý½ãþ~1Ò¾‹OhÈ¡ÕxŽ}B|ɉÏ/®Ø·åJû8g]ñÑˇ_\Quý)öpnÓN?õ¼0rÆÃÙÀÑ2†W|¡³&Ñ?ùœ#§‰E… 3ß´ßéø…3FÊQ Óâí¿F7±“v}½L0—LøóÄ·¡#ݸm¡ÿ ¼äÈ¿U2 Äyˆ¿ðÆùQü™Lù:çP9;c†zÌ1Çsï>¥ §€ºtÈt‰Ñj«Vüæ/ßÉùÝ6%éúŠ_‡{qõ< «'ºóÑØkÕ­Ôñ·-KÞ_<6tRƯÂ?ïÁÛ–±ôâŠö¨ü~þíïÒÉi6«êw~VP˯Wß\r-|Ë~þîE_Ëgvÿâ'ÁÃÇ_<:ûÔÀ‰ŠO7ÖO¼ûL$xâ­_žxµ¡<ñªïŸø®:qÞ¥·Û'ú¿uÊýc¦ú5ÇL¬×W\}À˜þ«³×S5ëç;×ÿáÖ³ÇO¼:1pü«ýv ß?ïµÀñÝÿ"p|Ë}ëÇ×ÿ;®>ˆWkÅÅ·¿]P’»ìr­øæ}v‰­d±V|󑙃/Ö\÷G; ¶VÕj¬è‹å]ø#…)¬µˆ=©Öbÿ+cGᩇšf¸x’0®Ñ¶\¯ß:rF`¹tnòèm´aù F ^˜x5¨Ò¸ÀÀþî?è™»$Gc%‚)ؾ{r'½`k¥V ¤èÍÅ?Q@òN«ÖAoîÐEo kB²ÀOGÞ}+üT=µ÷¦½·žeŠž†®ýW\‡èv‰¹¢3lxVdâr—À}¤ùV¹;Ðx©öb²­YÕ£á¹}á«÷)y¤/¨ßAÆ(x$âwcN§_%`J[êÉíY³°è£9xy!¥Ý3Õ„fcÁ¯wT_äG_þnV²¾üå{ZXÔ­SG>h¿¼.·cãp«?4ùуq2£XSHt—‚H }v{H°°ãÉ;MïöEA ÿš4-îúX‘½.±(A¶X>|Ú?õÂJ‹Å¡£Æ¦ Fô¼ËMpQ³’Eíš°’Ž ¡eU©ž-⇅ã¦oU‘:Õþ7¥3 *äJÔ—²ë_›ôUÊ·CìÌ|zPoî¤ÑýÂ_“.µ(&Lßë4¦\™Si,/ýì«Md”À†\o½[’44òÚ±$f>|Á™0(k9yU–·Àv.ŒµRø¼Mehͬ#Wfºá2Åqë“´§Yh穼nÔµ-~w­ÁRc†’¦–Q)b=^Ñ<µ×hMµ´¶¾ëÿAαçxÀ›lÁVÀI 12ªÒ¸©¹cúÂÍw±wOòUb«©ŠB+È‹x†$T‰|ç/m~÷èN sWÂ!žZ¼‚C† |8vVe“÷ñÍ}‘Ƭò0jã ù"% P ƒ…-Tkœ%•±5UèF¾ª&7ô¬ ]ÞÅf®ZGÔôz:ëU>üL©l´i.ftnè‘ƲA($ÃF˜¹ ´q±(á*_HîU6›Úxòáî]X Q&²§‘·E?Ð÷Íÿ(„!ãîÌ\W7^âD–ëÞ3ŒŠBº"NíSA A²QâŸ[G·U1ðr‡Ö¡Æ+FŽí`œÿƒþj;‡m7O{î˜ÅËÆ¨…î­‰Æ`ÏŒ´=Ua{Ÿ,Žy¥fîÓækücš¥†2j0ИR0‡o»~HúÜ> YPi ªÒðƒžkÿƒi  `êÂy¸ãÀJW¶æÃ#Ÿ¢5vª¥¦/<æ_¥e}G>……üvÆÄNíç‚›b 'Pž®Õo´Œeæ¡Óšêò.¾”}¶Ï—rÖù_åKöÓŸùRM' cÇ–ÖïÄZ£ùÐ÷z•ÞÄÍN ®,?¹P­ýcæ ¨rÞ SÁX5nÑ®ç°0·ßü§­ ,œÕ0sî¬\øÍG #ž4)œ!ÁU×ÇÓ¬ŽhªC0·rÕH´R tÿ¡goÕ@Ò±6tvî‹Dï“õ½jLé<ù¾Ð½‡ å&nn(¾芌ƒt°¤šÉÄÃp"Ê-iX]•5ð:•"MM½"½Ì%ð-q5„gï§£“\­Ô#hb¨¸Ž•Â~”Nt p°T È7ßG­¡ª\WœÀ¨c‰ñNòT¬\Úâ0‹Bœ<Ø~v¤Nˆ$²]RJÕ·ƒ>âa¾•²QEQÇÜÐìÙ¦Çp 3*þê›L ÜüC×—ÇT£ø¢Tä E†EZDv×ÕÞòº¶La¤ßR}ÓÒ–‰ƒw´—¹#Hì?`Éñ:¨06؟ݧ áàmM a¬ÛXÊηâHÿ­ËMÚ T`fÚ`G¯—ˆ» Œb¨ÉòúªÑ§Õ¶ðÍ%Ö]e><*Žo…îk}² ªå|'œiÕܰÜ(zxX¿[­àð ì w¼­™4«Å.§D¸5–":…l½Å6rOÜôµ[XÿÞ*4 Lƒâà >~8òH¥¤o…ûÑ5ä½iz¬·÷µØ $;÷ÊùR¿+}²_ Âh°x1MUÏ´æ<é¤Ðk­wԽ冤ü<ÍR%£õC-õ§ 4æè ÂJHª›ßJ-ê]_‘[\½©­Çš_¹#o}bS{ï fýDÖ¼mßïƒg©u‚NmÇ*Lžª_Wes¸ ´%b« <¾~†|G6WÅ»0Ô´ƒ³^?ÿî?è1SšIÏ8›Ë³ãß&^,J+¹1­BèÍíÔ±4Ç* «:@Ab¾\VR±01ZˆXüÁ~ ÌÏSÞh2ïÃ&ÈK¤òáêóT7%bí°©™²-Ðó°ÚÉ`±˜é[;éY+Öµô±¹œÈU\ôB@¼lW—¯-6‘ÝXü%U‹iCšRªP sà)ŒŠ-÷€êS>ƒÍ‚¨íOɇï¸Ü̯`èéeÚÂJßr¦BTÆÑÃt€FinÒU¶s2W íQq þ¹ž@ þ¹žÖlšòѱ„ zd\<¿|S[A¨Û6ÁƒÞ•Ñ ¨!I‹]íúŠÅ3D„ĤÎAñ*7›Ns|?þ~+ƒT£©,*Óçd‘Á¯šâRkUÄì Fi ÊÄŸF“öÊLŠW6è„iSé"-ñ$CS"§ßaég§0öêi&b˜…mt|+Ö‡årþó ¾KаŽLˆÊŠ{DAÈ<¶º$Ôð¸Ñ@AG&ÉhyrÐvâ¸özùi2_èíSsᇦÙÚ~_øG³‰ù9ýÀЧ—j« )$’9`ù4âjwà×T2æ·€êµÍ‹¥×iѵmùð˜p‚U2…˜„沋”tLÇcÎ% ÉJÊ16øÈNýeùÈ’-²«á÷jr¿•€<Ýë´}Â<õȸkõ´Ó"ŠÅò椚¯Í Ei6nô#¿ý®zjZ=Ña‡ ìüTƒ˜*å‹Á¾?õ*ú³8‚H®ˈò«:OáÕ|åñ£`<ª )Í…‘Õ„ôL·§O áлw ŒmÜ­èöÑË‚)†ðYÝ~¼áÀ v”|wÉ`~`í¨î#G5ΣuVýIF>׫\Åwù§q¦9u‘ÝS'8’6‚½Á6ϼÑÖ4:Ìš6é}°$µ˜‰‚I¼ñŒB±Ø8ïÀ„RÒP»ˆh£È‡[—ˆa¤RßÖ&Kå0O8\;ÔÖz€"µD%²Ÿ^„c¬ôb]ÕW›–-ÊŠ²Uï¤â&B›è$Ü”!!g ¼Âï@!D™0²ŒÝ¦j~Σ6ó·‰ ”Qþõí3Ê»ÿ/㊌ò±Ón¨lK¥*sGl~kzÃB1á´}6·ÿ´wÖä‡Nûü製µØðÁ~§“pIÿ^*my¾¡EÚ*#ïÒ|cuIUFú™H{SÙ|ä˜-( ˜ExùÀy"¸yÎj•Õƒ©¹ÈM ƒ œ„]PÕ|MKúÚè[ùHÇ´‘Ê$¦Oöˆ¤†×¸€ÕÌ«JóbÈ6bÛï'A [„v‚*TܱúË8tš·'±,æÃÿäÏ e¥® ”Ó¶Ú³W©ÎAå!A:,–;ëN l"g¯2̾FLûÒ+¾é—w‘$ïõ:‚¦zçuL’52ÓFÌS`è·^£\›ŒÖÒe»<£)VÕíUþQ4’Å“M°ÔÒ¤Ñé"§µ'kä(4¡vžÇ¤XE7³saWOé½i5í—Ž©¼,7yóË3Ohlê½F¦õšÊÜÌiÏÏ_0kþƳº¹yM¥7Ša§øƒ«Ÿ­U÷,ujÏ]†ÿÂ'~Á§3ñ!|óšææxÆÃûaõŒò*×Vš;+•Óª2wÈÿ:O-­®tŠj¿Ä*ó°²,œ?ã¬ÆyM ç{ôÄ–xûYÜz¤iFs¦9¿7'—媷ýU=­NB=lå/¾…ý¦lPj}FÏ«Ÿ-ÓCç{HýAžÌ–°U‹d¢[õ¾…òÆÊFl¸>XŬw/â“*Mİ’qÄ–÷ÄÀvA™—¹c.¸Žmk’00u´D"ˆ¤ŠÅ˜G(ýA Ô0n”íi6:EgN“œí49A|-E.ä%yéÀ Ej¹et*4^£28Z’ MéØ/¨Ê'k&*ÈáUGYXÌ@Vt䳓›¤~J“Ÿyÿ,*¸¥ÉRÈp+Ø´¤1c®qVpd K¿PúÚ mÚÝEÀb ޱ4&:&ëáTíÏ6û·|R¾ÿ$(Bl­bGgù`5¿°¼¯‘ <Š}:q—cû[šíðç´³?‰ñyÞ›\¦ÂZh}¡_¼¡9lsGŽJÿé$®JU06dj'6Â˜Š±ƒ"ÏägSŸe:¤Ø’ °áß¾¯‚µC÷Uá2«ÖY&:UÄï˜8˜v™ZÛ\hÔ× v›ÎWijÅ„r§ƒ™œ±-Nj@f£%[\ˆØ7DjŒ©Ç8ÓÿèÕÈÉ]\§B{€lÈ)Í=Ø=ŒsHµàŸ¬ù®²üæ|øó“7ÎxÿVª1œŒë€nyë§.7,~YC.üù>´Ç¡æÑåó¦¯ÍqôÉE~øCˆYX.ì‹Ì¤„{˜?ÿz×d"¥™:Äb,ò\¹ 6my–t©¥“Õ6hô<×ÒÖt8ê̪1“Øvcqz/]ŸòÁ-\\Í_aéõzéÚÎ͚̂‹yêR‘F®×ÅËŠ5@Ügá­+pßšâMŸuBã<iuÏ"Gò¬y3e“šªà}·O¾ð¬ÿR_JÁÆI|Fɇë¦[æ:»¼…²ŒS)¨Vžj8Œ^2u,6eìWo¦%á=ß7}.U*ráÃv°HT¨C¢¨8²A¯×™^‚?Äe3Ö‰Lƒ‰-›@‰j›Yf ¨rÄâKB¿\×"j9_ü\äkRéŸÊш\ùÈ̵bÒQò´8$Ð-ZäN›‹ýI0)ƒ^ ’øüîâFE¾®¥Gb trY[!ÒRƒÎÚÎ>SÕ*1BVB>¼éä’Í ÝpS`‹¦ð·¡ÚpüU+(·ÏÓÎLΤÀ ñàbß}Œ|ÂÙ*Í# k£0´øº"ã^DA€4=È Èȼ=ð©4ÆŒQSB)gZªÁ·¿/>ddagŒ¯šC¹¡¡¶E)lQ=4‰^¦‹¢ûXV–†³qrI"VƒÓn ·é"*¨ÔxªD‚šŸ4i¡{ËLQmAnè^rT9ˆmRN=Ïø™Ôt+u¶Ûv'/’C«“IÒÉÎGNzÎ0LwGDˆÉE´¢z¬AÀ‹âx-aFM±»@ÏJ"&æñá–Äe:,=ïúÑöHàÜn›?ZãQÖÄcµqã´­?Õ6!"Õo˜÷QÛù^a•T5K³Þ`­çòki€Z£ôxÂrmZ;€ëÉU\3K qGµõæÂ[n¦æj”5 ÊßPìòå¥PäW>ðá_ë‚XÚÜ1bµr­‚>1/ ¨(§^]N"Š;Hr€ØýûOöºF]òÑsS0Œù‹ÆÊÑK¿»Tˆb-™øBЧfÄþKìCãZ|û¿(þyLq…$Y%A«€`f 3µFÉ*Mf¶§(ÒqàŒÂ1â ÅC¿hÖÜF{®àx¢ƒÇU*0º)_öt&™‰X2÷æÃ-ÿ¬5•M»Zjw"Ù‰mUŒŠÝ+–dr­ çUº´*QHØ”vôâ$¸îe¬?PàzµÛêU+Á캗%)º§ÑóâV@ÆŠ$gñ fŽXÃÆc´N<"(ÆØ B/t-_\ºSrî_@{%zrçL»è<·dŸ±É0œGrÄX!´éˆâ¹%3¡¡~ï Nù¾0m#½5‚Íva>•ðhϲ‘¶${ÐÓ’Žu À’ ðv ]‚.ã£úøç¯,ïÇ8ò~0¿ûº ´E.¬ÀwÌH­[^-BŠ {ûS!N¤ÜÀ6‘=šûltaÎÄÕ†ü/À÷™«°Õ“§w*",ÜòJ©L%­˜¥ÂL¼;‹)Çz’•ò?R•`mã·D=“C$UËF.Œ¬]fÑ) XîÔ×.,)%‹Yd·‰Zo.1ýAfSá0 q÷šÆqzË5Šì6òç;Áø¬¡±L)Þ ½Yò¦Dkñyó¥ÝNGâiΚZÖ0 F+s8²âMY†ÐÍ;ܳ¶qðHš¦ΨïÔE$±± î¼ä=Æ pïŸ4˜L:ËÑ?1’=ìz þêñäàU&ÚöèÃÐ÷M¹Cóg–”c•—ÎÀúQQX O¿ÜâQW¿Ä,ÚÑ´ž5ýJ‡ã øØÏÄyÑp@Õ_~$š- g|8þ»Åïrâ¦XØ~Ûg¨^ºü¿4T'”Â'iÈBÝr^l5(1ºwH£°#Èx ó{û1äBÔ)µ1—·(•n`¹TÅ«d/ä#•O;­’yLº†U©¯¬î-MQzç†ýñZ¹†cA»“,¯(׎dæ³ÇÐÆ0túÙ& ¬dzð¹TR±•Ž$Î_¶Õ‚Âi;ÌBXb-Ò-3acÅeô}V)—ð_h­° jeÐz—J´ñZ€ñ lqM.Ë‘ÃP¶š\èõi.+•÷,€]öѪÿtÚ0EHƒj'ÝÜõAÇ tÕµúLRaÍÆº²=ôS_µH<R·è;ž†m[2î8Á",ÐÄý¥…q#¬BŽ^±åšá69ºu—ØêOó·mÁvÛÝ?÷.W;¡D¼äqX{è¤{1¯J¶'«†¬€et:+b¨ëo Š0Œú)u"wu±-£pW`ýå‹x# ýàÚ9ß‹H`FÆÚ 1Œù!²5뜻%øš'3€æ©x(ecr<4Î…a öÄ®×RT`•vMØçÿv´ÞçÇ 4´1yÅÆ ¤íb ½6pÐp};™ên&ÖÅø&Cõlqf(Ar5‰lÍàs–Eb¿1Äw:NgèƒuDÞëÆ:ž½×ïyõTÖu»8ëº?y€÷6ép÷€4ü]mÙ’ëãZ²h!J¬¸ü@m‡Wà:žu½7)áטÁh:2¯ ´•ꥵçdÚ£˼¥µD`‚ƒ½Ì«B.©øjï<ëéßc«U»QoeŠ2Û1«%àÔ“B¢ø:áª=§·77ñ†G ³Ð<'¡»¨* ³´5ª'V×Aw ¬ïËÀ}vy¥°@§ÚZ¼FÅPVÜ"µŠz@;¾¸é‹A` r÷Gñþ/ã†ÿgÑZµdÛ…*.&>(Bh?àú:pA{q¤Iá¨økWu`î"÷Ig }Wm¿¶C^»ˆñãÔf=ì S¹ðÓMðVÊÒÎ~M´0Im‚S´­-Ùš4«aëÂÒ²$šù •u2YGŠà„e,af‰Ä¨m‡?@)£pŒ¤ºR¹h’ 7]<•áPÂr‡ÌB~I%5ÔYéã-KbLŒwÆê¬T¾Høj{] š ®$¥Uic}pa݆kò;òRj´Éû@åF$eó«\˜f. ü°v®pŸ$û†‰Ó˜ò‘T”ÝP¨.ÏxÅ(UÂ#©×Þ<«U'v”N]ã.ÃmžXÙ${x´Ý[pzy •¡:Dª›íD‡Í°W.D§p\µÞ&“묮T(«§‘&íZ%o(ZsƒìäwχÞÿŽö~bñAœ˜6·Ä*ÂÅ¥Á† Þ§Þ€Âú''b2=û'b£àÿËIÞX³ZO ¾¢N^ÐÄù’;ì ÏêítvUÆFú¾±ZW]²Aq¾!‰öç,ñmªN]ÄH•"æ£sÍGãwÀ-PVµ”,«/å™Ó#/qh ÃmH×-ŸŽŒœ`J\çèâb~K6žˆ‚uP”{=½ôï¬/ùЕŠíÑ× o6I ìÒ&É©c˜Û·ó(¯”ÏÍ u¹ý§6EÂ3Óåu)cdÿí3F6ìô_#Köb|7Ms]_žáöÃ_€ß “îŠÉ8£@ pËë"å°Ρ;Œò -SjC6ÆáTá}¢e…Þ:ÍĬ«Î ýÍýô˜‡µŽU{Iál”ßíÔÞÅ‹Y‡!˜òË%9)“îî½IG5¢`õ=2N-¤±â E=õmÊ!Šì¾g¿ÃxÈ¢ôÇOj•mMz\yeÚSØÐ@6=o§Si0öÊ„>Aª Âï6ó'eR5ùÐÆ^¶+¸ ê@g7æ*ÖµâU…*¸‘×*œ§ÄźV¯PEwW{E _Q¸UØMóÒµQ†us¬òƒF•1cˆ!Œ9…¤ÿÃ~üŒ…ûäÄF·ÆråC?;"S&c(?hVZdÞ1Ÿª*Š€õÌ. ¡wñQÆ*(åÀ´ÐM}‘¯ÿÄ€1Œtzr2˜´PZéŒéÀ‚hž‚iãUÚM웎ðG(4ÄHCâRÈDôó­#š}Lèd3ñÕèK¢ÚµbCLj¢®. ¾€¦ŠöʗɶÒ4:§žÅ÷Öõn¬øÍ«½=·´ëdžØ£ÆÇ×l»éhœùƒµ‡YqŽrzñÛéÕbIâFš žz¸ô,.²cã)& ©ë8¾7ø3Aì˜'ª®ƒð¨£G+C‹Ú/9±vþºy§²D(AÍ­ªöÖà+ŽÝ¼‘ŸZuTkôéXv:Ä;»|;Oßv|SQKÕëhT°t ¼ ðl$W÷ë©v³Löè(¹ï`Ý—V>–ì³sÔå›ÇñTॠÁn`Éî\µµxqgÜE×Cugª8–”1BÝ}Á*ÀÓ°ÖfZŠŠÂ²„3"þÍ"†Ð_j@SªÍdÁæâ9›Ö+BO¢»0á0§-y™Ó¶Ëg•æþÇí&¡–;üDý•7õßXï­Π“y Hq H¦“Fhig*«ÈIÒT*^‰;<ÖØzpäUèÁÑïÅÖR¼nORV8±ó6œ„!|èîfÏCr~@œœK+Ô¤hæYTF?ÒàæC—ÏsiT“Œð·¢Mšf‘ž ‰{ÿn+7(ü[&s Êgñ׿Ãwß—&[;•Æz×C/ÿ 4ÖáÙG•yk‘‹:,¦šb#¦‰N«îº0Œ~·¯OÑx:†\,ùðÆL(˜ä Ž|kùð¸ŒËÕÂñÊS/fžòšUrBgÔŸA>|Èñ×0ýüê89EM„Èž…‹%ÛÑ,k3Ë>û襓U¨ÎIæC¿­;Z¨²¨Äg¼-¨”2¬£Õž†4e(!‡xFgµ‚6O÷ˆ§Ù!/ÒR*³X°¤é¬Ã}•.Z©ãAlŸ vCþ¿¤Ó8&h‚™]d<ÍQ˜Ðߨ ¦oÜ.šÄŽ<-Ç.óû©¸ûª¹¦è¨esÀ`ÓèóV‰••’ªäB±I"ÚDm¸æ#G¼ä–ÒÕd*z¿qgøƒ kGnØŸ@ŒweœB¼Ê… 7ö@D[ݽ§³"‚;wìý:;X-†þM Mç«ËHÄ“»p6–Ùýmè¥=&”)éY†íÑ„íÌü0Rd€*ÊÌÉóôª=®Òj:SR'4‚}t)© .šUú4¯aî¬ÞÞ\l‡É2‚çœF_§Œ[Û‘TN8ç4ENµÜ"K,Œ” «”šûÆæÛÈØª®c3WµjÑŒ†yƒ7ê¬-ÇJ£žxÕ%™·«]O¼¦º¦˜ËT»¤MbZ´úe›”—&öç56A3W÷¾ÀÍ MzµL¯)†3›½[g–iã ”m…‘Òhú€œ!4´¾iþÉ3gÍ^4xŸ¦¾3NúôôÇË4–Éo3Ô°þ¨È$úJÔ̦K’ƹ挢ð¬¢Xk`+›,FÉt Èë–Ûêr%å˯³r8«e’kuä%ö§J#ÐŒ‹#uO1E9 ë¾ö<³¨n,È%4 ÞkÕÐ̧_ÒÐÌ¡+Ê¥ #•¸²3·TÖVO=Þ¼|k2Mb`Ò}%1OÔpjPò*&”eQ^bȃ ߯Ã:E¼ UZ,gáÌO)?G®5ä#ÐKOþv1]9î‹»DÏ=dð±s× 7BŠ},T H±&iÁºÎ&ç:gK•¸”—Cƒµkþȵø'‘}©`;ÍSZ‹"ñâòÇ¥SÜ%~4à´ Ý´ß—Tlºb­qÐ’|c¢KGøâSYJ¸;â G’ÓèvùÊÈQ;jk2èEÏ {õ/ v˜‡ßÈáÇ2Õ=4¡¢]KÉ®¨ºpMÎ"œµÕ0ìe± U6jQˆÀ ŠŠŸŽ'h…xàD†ÊƒCÃá½ØeµïU±+ˆ.*Ñ×ÚÙê¶Öy+¶ ÷Å/Ï!Øò›Õv‰T±M6ÍÕ8Â@1õЦ#íí*£”‰BaœKŠCÐ(UÓŠÝÉŸfœ°D.­ Tà õ€RNú抠¥wÏyM “é¯2KŸ‹&€ÆÛ‰c[ÝKw ;GÙ}îÎv«óÈÐíàŒ`Vjpo¬Æ2ИAÁ¤La*\‡šZ>ôûsa’ÅÉ<ÎÉI?›ééšœ'Äxœ 2©÷BSHP¦ãí$ì–Ìj8u–:UJ—?'ò½Pa#æS†¾÷´¹±ìfH]Ü”MBª¶Ïš)cÞª¢^<ØÒ£ªû ëNüZ) ¯‰Éw:­0yí’ü¥>Åoh]k«‰—v¡ Ck”ˬz3–Ìš^Ð$ØŠ`)ô÷§y%‚]1¬^Î6GEüˆ æ#H(v‡h-u-—aˆfÓä¡K¯Èv¡YÑŽßoU¥Ñ͇^x¾dˆ¦¤)—1s¼2Í8¢…eÍ8í6”•‚2’Ÿÿš%TYmplCLÊxɯY" Þ…‹ÞÇâ>Î5k œ1ôù*RA £7M»t*¡ \¯j ¹Þ+¨Œ\ä'‡ 4S@ÒÓ¦µTá\=Æ c ˆ1êi– ‚E†¼ß±‹•âÔáìôev"m3,@D… }äê$†ÉWAmBWû’ÂÖ$ìÉ–xš p0ø þ™¢‰wF"²Ùœ ¥2ï«Þ`†Ÿ2ê†ÚÕŒtñìô G~Øg”ùZØ%П;a„ µ/±+«›, HШ݅ ׯb83îû°¡Ç[iýêÄOÞpÓøÔ"î4‹Øbi]]Ý2ÌBŠa^¾øgMÑÀD¬á:P¡—ÄbKúÀí³¤ïÞï¿´¤'•·¤Çÿ7Ôy£)æ¡B0~Lj¡:zAhbs¼£G“Í,zØ‘*Qyìñ½˜ÛÐt¢¡Ó8¢¹9;§ñˆJomnô´×G&*èpdGŽ·«á©<ö¸ò7'bçнã/xîMí~šïW·?È­í[ÛiZ¥Kîžbî^_±~Û-£Gc¼Æq±qÈáÄ׬ZzæÈeçY}ôÈÜ^ÛÞ_Ô8wAnõæ_ðåAN©ÊªJ¤/@u¦šÎ̘3Ñ,Ý_KK®Zf_ŧަS%ßæ¸™#*9ݯª)½Š¨R]™É檺:ý©ú݈£ûƒÛ0Î|ݬ©|‘dÈà™ãôûÔ™Q%gjKÎ[î[޵¿ãørWo_1Ú~êúŠ ·us4K˜É(inÇEÜÖTšvâ_ËÄÛâpnŠzÐY•ÈwÑP{Q^äaHgžÕtú‚YÞšÊææJ|¦ENwÛÆ(dŰº‹N Ý(¿ÊÌP÷€ |<¹aÞLœ1•ꋜtÚéF9 NlÀàUG­¡ókõe-ˆÛÊÃeÓgà­¡lnbes™9èºh­é­–T*s’z¾JàBþÁ<¥"Î ‹fÑe7ÀxÁZ|Q+:èú˜"—Áæ½5ߺµÅi C5®5ïŒÆW;ïÁëà‡µž¹,…‚cþÜY'X½MYÏI­JfRÈ3‚òÔxÒ\KðΚ#HWáÙµ•8ú:1Ì*„’«’ÑàEð…xQшÁÙ¢ËÄÆÄ˜+R Ð{5÷I¹RwÀç뎷á÷½+Þ|ÆnÛcéÒ‘–LGt¦J¦äQkहtñÉX{`Ò¦ÚÊŒIªm--ØÒIÝ—Û<5ð8̓©]Û×Súî*ÙxÚ¾÷áÖÿrã\Š"7öÃv7o )(ÑHâ$Æñ“IÌ'ÍÈ ÿ:NâàãYûŒ⯠g͘¿“cå:üž² ¶D¼d ÍöâEÏWX4ž$6 häñtp>fRÁWK–¤YÙ™î.Z“Û!:ðR«Yç lòâyMsŠo¥;èë–•­Ùíx\ Ä©¨î%ànPF¿Ž.±^‡6~Û—ÜW˜Á c_[:]tU¢Œ@—èJ¥_¬©\zæZØœÖVâî6cþܹ³æ5yŠjÆš2„N¸£ñ®¸l°Ý‘kGÕ76gšóBÞÄ*W y–º´.wú´ßð¾-×°ó-I¹È™Vò-´êtµÞk°ƒñÿïdGƒ*¹·†­åÖyÈÃ)‘øÙ–dNÂê)9'¼ ú¾VÃäÍ/CÏ0Ï­Äð8ÉIWÇèð@"ÇJž@cÎOà“&³ª^ÒKµ4'míÒœ¥iZú\æ%giÍ•œ¥…Ur%bi,åÒê²9eÚ%³¶ôm<KγÌ+}LƒÑ»Åb²a~OQÙÆ¹EÛ~ ,Ü<^le,ÝÍÞ®”ÀVlûv07eÝ ë­ à-'F4"ܑҤ©«âÉ¿J±ø˜ a"LS»ÙÁÛ·›=þ⇉7¦ÌnFŸ¢›ºCzŸ˜àdKåQ¯¶-Õ¸K¯ém™b:âpT×Qò6_‡YîÝæ³I—ù‚ò–’”ámåu«Ç \ÂÿÏt8ŸžußæÓHÐÑ3ŠXï8mœ.{dÚBû`Ù_9.øn\›ò œ#Ž]{xGSg‡îEZ÷|a¯ƒþSôÛ¿D€,ôåæ%#ÕudrÂÒ·õ¢RÂÕOQî'½îÕï¼TJ¹Œ¬ÏÀwÐgäDøØ÷›-€¶!ÜÔ„e:½ÒÚ Õó¬[0ï?o2N1œ>D&ÚÀSî½^P ¨·èoÖËÚ5A«4ð`&(¤k[7okqSe Ö$NØ—›®ÅyÍ÷á>oˆ *‰3±x Ýg½îô­ö¨ØK”7o$­iÐ\¯£ëppLžS -Iû{rá+>ÑuT_ùBU}5VW¹¡r«¨=½¹ªë..TÕ§»àÔÞ÷Í+T«éƒÌRvÅ'$ÌâíÐÑ÷$‘ÓÂ"(S0sx„¿µ… ‘è ìÍñÀÒBÕøjŠSƒ¶¶¨ ¶+Ê@'Ý.Ï!ª¾¥Ýgª&`ƒBè øíÿ¼W¨šXÝUãÓãmm‰·—y’}ËÑ7g UÇ ê`ê}±hn–ìÓæ£`*:íd+!F k )IOt„H¨…ArÆÛp˜¼ÆK«z¦0a#ñš „+Of¥<²yºúãtåcÁålÖ —àrK˜ƒ®.?¦y¼Þ ’÷fµª«àÏÕk§(WvµþK‰ækþ¥êÚæ‰ôFô媇ÀKƬ­i7ÿª7ï›ÚUó-ÿ¥ªY¦¨Ú|fãæ£ÉRɼx³é½ÈÞl¤*´q? ôFRš´òÀ#Àa§ÅO)š‚Þ‹¨C¸j¸ÏœVÝ•‚l—Èr^Ú"ÉžÔž=¹¦“NÜÊ#ЛËþ4VÛ^Ý›úìï SzžÄÅÑ›ßãñë ÕêÈ+LEŒÑ¦¶-G„áŠD˜8®HÂ! pOV¥¯–¥ërS»’§O‚ÞלvÒЈ)ÏüßÖÕczs³Þy„Êg-^¼uu}on×®Ót+rØ S0¼eÝ)[Hà3S7ßoƒçÌzüTlýÉ׎ܴwa =èI\ª|լͷo›¿ù|üµìš' SŽë…GœýÑÁøˆ®'ß–·ÁEOb²Ü{;:}óØ\ø«ýš­r_æ£CðYë+.Ü£Rî¤ËêíËð*ìà1½ùFé¾M'½‚èbüÖ,E÷ŸÝö«Bð>XîÐ?WÿUN{…Ú|<á8õ(ý 5¾p”^¾XÚ{Á=?áö~ÿ·7K{¡ž¤…%]JΙA{NÄ@oÎÿãȬâÈòçÇÞÉJ8ÈÌ0³Å‚y[nÉÖ¬¥S3¶îW˜ SŒRRèA0md½¶}ëýµßXë]-àY'oEg00ýðq½ýcÕùçÀG¡àÉïÔ´fE´éç”õŒ—i¶©ñªB „GsP¹-Â,!ØÚ”fЩ¿N6ÓÌWPenbÊ|t1k³õ“'7 ÜÉä#gQ¢+Á‘eýg×â$.º4,>æ¯Ô¦'H¶Ëwn$™¡ÐÁ¬ [af8³Qé^V#óá‡:°2¨NšxE ¢”Á šè !}`(A&h^’ÿ­Bgâ rw{Âf -2ìbqÒ™ÇÈÎ-DïRœ¦Å\º§y¤Êä|¿NÿêVÂ{ «9òâj2V7χ6Χâx\ŽC.v åfÙ£ ½&• mGúÔ0 ªT» ]4˜D¨üžgšyT¼¶4';’"NyÁ˜Z“ ½ýPc.ô̱<—D8›Óš—R95šJŒbŽÎÔ*¾®>c tPOÌksnØm~±ôj™xÖ±°òÍK:–vú§Èr+¥¦¨ô &GKö"§]úD¦€”Rr°°S½DØ(3ä D°j< ŸÜý|:àWtúBÜÝ.Öˆ/ƒ:­2™¶ÞqW¸þI0קǧ-“ˆu£#%C5î<=1ˆCs&â®.+ÕšJd;“rµ¼ Ée½ëMj°Þ²DŒ«ÆÜ\ø–o,í½bÈ2° Wnm`ÊHø0Nr³Tl#ƒüˆáÿû:4Í›ÎZ;4 §G¢Ó)U€F‘à÷¹ÁTk….ĵ>5¾ã,0¦\UÐ=9L‚#WJ‚ ¥câ-34½°ü›¹ W¡@È6p0ånýÍP²‹©KÁ“ˆ™Ï Å*ß"-ö‰ò_­'ê´ÄJü8j}tÅ*”·)ÛPV.Ö> _ÿ²”‹ ´FU¯ÉL J~@b{ÁMSÒ°~ôå¦ÿ‹ O¹½V “ˆ7„œ¤„ÌØ—’#ËQX*++JD£\Æ4X¿“˜kr‘ôX\ZçÅÛò‘É“™Ó™PÂÙVE÷y”fÏEè i´‚o‹­’d*|ãbs|š¼µÇ3ÞDW#2LRÖ˜JžÖ]SaÙ* _uã1‰[Wx-éš6¬$_ÀÔ‘LN«gô2NÍ&åU(z@VݺIå Sr†¹5µ—„R¹1è@ÎP^Mæ í¡lT7H^½SÍ2Ð ö¹vºò©`wƨ#¬>ŽãséJÇ;t‡û§Çŧɇ^abY \ªW˜d"Ññº¡3Ÿ~\5°a+UsA»'òáå_ׄ±n{êç­Y˜>¹ðØ€ ˜muâL¤4–N!KP± @ØzW§M©–sºn·K{ÆNêÍ ¯Õx]uÞäc–™=0•mïÈGþ²žFý;’ÀŽ»5%œÓ·û»5ÕžŒŸ‹’hèÌqR¢YJð˜‰ÔÌQIʱ< ‘ƒß¥„¿hÌÁm.·“VŠRC{¶#üÐ2ª¯ò®[ÙÄ.53ËGœÓèÎ ,s†ŸŸŽu þŸs ƒ& “Å¢-„+~“d2›ÄÙ©Èm›HO»á?*5’ûiQãǺ¸05iIM"-¾„Ì/¢œ  ¾§”½<ùbWªOl]…¹ù¡ûßï¢ÞÊSmmɱ\ŃKÁ”úû³±pÌ»rR,ÕPëˆ_;´cª$nP#)‹†à­'ýŒZŸÆœKÍ.AMQª•÷ŒTexÁrª ÙiBÄŽù_‰„Å’1™sz®ÖTV•–Õ|\ …ø…ÛSX¾’Ö%~Ö‚<õ3¤3øzÙ´]j¯­/¼r½ÓGÕv: —ÏÿËÉI2¤|쪟ËT˜k UfŒ)~@Áøù[»¨g¡ ¦iæÂ…5]25 Z'¯+,í©Ck «óë+žM¬7Nl‹Êí³-þúË/õ%Œ#_œF8l@Å®i–·`!L©ù',l˜;= óf*/Cnfò÷…qe*:59o¸êŸ¸vÕ²­âJ/¨îűޢj‰ÆÝÖ,çÊlP#¤URGARj[–ÎsØdN©5›ƒ^Ô)NjW$ T0‘…†©?ˆ© TèùsÍØ5–¼àÊù:¦uáÇíðV8$CB‘Pãò垕ě²Úºn’Zª{hQ,IÚbpÅXÏoqA±ÃiÄUA!I)¯EEGµ„8÷ŠkèÝÃqd£`ú×OV‹Ó®& Kjï®g˜~$Q K¿vÕFIÑIz2éýÖBðÉ~ÆÎêr``~}1©0ÚDšÌDuÐB²]ö©²–­&ÒSRÄÞ#‹pÏyÊIQ©¤íJC%ã[9Ã+£kíÙcœn‰gÒ'ØJ•í0E—qj…¢š5IºÂÒ ˜qßld¬…ÃÎú¯u¦Ú´ “_ë»6X:ÉíôSm°í&âq•óœqñ^QN§„Å·§dûQ˜^p{üÈðö&¼øPÇå²Õ«<”ãðÎt'նަHïG‹Ëø0átŠ)MÔÓP(V0°>bÕ#1¾ÅrÇZUÝ­?»s,Aa5Ìrdå[¯Û§RxO¦*f™Ž¾Ð§+à'*œPœMO¼Å—`ÌI˜]ˆ~ƒö‘Y'\UNg ©qí1•OÌ”‡fJŸê|èßmsíâ·Ag¤Ú˜q9ƒáG~åF!gQ$/즥9Í qNf³Ç{LonÄ¿;À¼,¨l²©òsðL.FT£UdU¹.tIR·˜óSA Ò¤Yíñ •MÌ/•.¾&ê§^&<•sDy¤gs€¦n\]}0-ò½‰/_rOSl„ôÿa­™LýØ¿àý™»Åf¨ËE–½ MáÅ‹éð(ò‘3ç1æÎSyð4¿h•YëôY6êû²óAF>¶K·­îc‰ºxÒ^ù¬_±íª·¾)\G Y&n¾uÓn½½½ÈdRpÈOCYaè±³Þíò¸ès-{{Ù*½z«Aʇ]ªHй+¾^:äBR òmNÑÚvÈ–· Oª&åC¹ Ô}5¹Ð¦Ÿ*ó—f†¢e nEó@è½bа ™XÐ6NtT ]”/¹ãGjVå#w|dùrÉ´ÆÇпð™ÁÉíP=ܲéÉ-¶O>râëââ¤rÏ_:V ¼¾ý˜–K>K%ˈ’íÆ&A ~ _ø«ÆòûcP °ç¬ªTCrQj˜˜7qQ>ºöM¢zÖcŠ!ËÛ xd¶²âòBeúH8ÔPï Á‰·Ù|œ'ˇ[žÖ¥I¢;ìÔñäUDž<ÜÌÅ/5!tJíÑ®ãP€^H‘ŠUˆVü•¼€A¡!õÙ‡ˆÝbNS«êU°G±óÎtW_dc!¨Ä8¾šbZÿaÈ¡²á0âï-¥ìDHÁã«Oò;OyðŒ³gj.2÷ hV_øÓO¬7Â>#;*OIºWRü¼¨n"P@ŽÇjc«c­Yò¾š°mg¹¡ço@÷T_ø¶wÄu‚j™a6ÃM v4±Ñ¶BÃÚ4#ß8 »lU¬Å/¨Ñ­ 1!•´,vîÐ|dèíÒ´²EÁhj˜wœY cà”fy¢×a·žiŠgw}žhÁhPÉýs~AûÖáÓÛ;8—c1L‡‹©µj¶=AÙQ¡´á.†©{tµ{ÛÊSÄK$N %“ÀÁO"Ú'Mlr¹açƒz,?妌­ÊGöúyتÁeŽP´tå êö:tE hë˜|Œ>Á°|%½]K‹Ð»@.Ò’œKÞÎî|xäI¼Æ;Õ+•FFW=<­©.)v­)lÔ–P•kI'®Ñ³€ *„ߟe×¢&¾¯°´gœ8)è+°HXMQ™¸‹¾‰Â³4ÈŸ6/1’§GƒKÄ™Ò ÙšŽëMæÃ—Ÿ©¾Èö$8í`K43žÈ l¥J¿AgU›õ1v£)¥,X8LD.ct*«I¹õ€ °AöèÖn%V ëx+…Z¡‚L±ë”“‘‘¤1Τ"S´îY‹„)Š8[¦À,™¢¨ {rã>^W_'JV°[P'õ&èænC}B¦r/— ¸ýèºÜ-du³ :›V4vXäêÙƒ)!´ò:œt´vM/%•H»Á9Ò©½Š‚T…Åß>×Õ_N8ò_¸®L·/:Ú·§ÿ¥]'÷ð?ë+î¡ÍV€(~CNŽ˜®pÄÖUÑÒ­D™iÈ¿š…ý½/ìü®¤0l®WN›JÇÈó‘ÆHîþ«QwDÀcì*jŽÿç;Tb&‘À?¢BÎLWiÐûku* …ˆT%PEKÒ}¬’îH² JÊc Ýzµ½ )S±5.²˜ \EíXødÆS\OZ5 ˆì¯TàÚ[ÌñëêJ ìýJÁVèG¥ï²áˆ”ðıSÆŸn1 ¢‰•ÝÿÍ xÀÐ*ë$· MhñA-¹ð¸Vé¡‘JúVt1Ãèa{¬FŸzoƒ)Û.õ×1÷|±140å:¿£Ð¢vê“R0Óh»¨;õ*&sƒ­qj´Hƒˆüü)½KR¶ë©ÚA½ë c™2¬óm#¾(éELÖq$yfP U:™áUszú?oBOî³¶¶; -¿ù^éâ÷ŒbC¾òtøåŒyy³z#"ºWÔÍÌÂÚo¸TašÞŠVU×`Ö…l>¿Ó8“.M–)PÊ~+*q‚QH4])kj¥ÑÛ±Øô-*/ÀظH˜4]y4¢Ô9¯Ú†E‹µzUृ93ÉXlTi'ŒïíÃ1®ñ’)97~B¯¿Œ‹õ$³rîAÏøvQD.¬DÛ«¤;ªÍ)&mvŒ2uaÜ‘~R®¦ô‡c¢‚, N7sò¶ 9ãEëVQ^«¦ˆž~ dÖŠ»)@MÈ«úDµÈö¼e%¥tPÜ{c§—ëš¼¹8æ¾DqàTÄ„A’Ø‹ßëSä ¤"»Æ3 ªØÃíéú][ƒÕJå>ѪŸ[“ ]·Zqš‡VU« ¾Ç_¿T>x… 2k £æu«ÑɦæŠ2"Ðq”]²_ c(1Š×Ü…Øø™D”¡À-Ã.  T’%L@Ù*¶¯%àÃâùeè²ô{Uæ€7PX<ŸžÏôÁu:Ä£Ðèæ ¤òà2'"ö«N„SfR>Ò4& Ô”“a•É%XlÆÛš̤i.SÞ×’€÷x+*ñÑd¦ªÏ" ÔÑšœ0ªœ(‡më[   ´M—8…ABg1lÎúÐ(5©ì"w’M„™¶ŒÍ4ÃBwŸ-ê^!;Ä*Û£_6A{Ü)¹a³žmnÄ{0¢êZÔ² 7G'MÛëÖ¬ˆg< ZÙ‘ˆ"3®6ÁD¦Bð?ÏBw’«¨Z©Æ@7ë!û8R3E ~!˜Æ­«Ì ØÙ¸â½ cŽR®XRè!Èanåx…=·“o&/€ÖÊVÅÛb5}ák?]ODoV:É"o:® ŒLä ŠßUçE¼`Í¡‹2d¿¯^¨ÑùȰ×È *s‘&¢ ûoË nÀ×aÒâqñR[IÑ‹š]”1¬Ñä¶rù€”µ¸Hôt!’k"rOÃlZË)_:¿£†Š¼P< |mC·F áÿä3QöéÛeŸ†vxêÿÛö©Uöïo·Í³ìÓõßþv{ÿko>~qEÕõ§âOÇÍ™ýÊœý蔵¥g‡TÞÜYþ W ]q¼œ7žÜÿé–÷/†ÑŠÆ‘ÐUï÷½d_{BÅ[ý÷Ïè&£mÈÑÏØOíÑÏîéëÖçz×9zøBó>eãáål1 9Òxû#p¼yûÉŠÒUçßx{ÿÕãùI—^9-†È4Ihð‡g—Þm›ûó‡©j§ µ^?¤º~¹Ž°¤'‘œ ðsÅ,aÄ:Unþvç'4ŠsC;NƒW|ÿØkgƈ+TþjÞG{Ú&ÔX2¡æÀ«mínEаšµ <ÉE´3á²X‚Á°›Å ·Q8Á’e?ô/J‚†œ*œ»ªTÚ[°ac…‚œ«Z2‹RmBÔÆzûwÅÀ3ð[°Ê üœ"B‚Ȧù%Òß1üØ ‡>ƒn&-/3À·&7t÷]PÀŸÑì3Á6—àXŒIôEv^‰턜!Läñ©Pb@¥Ò7Ä\dÒç]u~}}=´a?¨æütŠ­¸¾ÎH·c%Q«Hâ.Æ',m<¤v(ã(öz"ÕÅ^yÕ¶«^…犢I¡Ò Ê|Õ€0 Bÿñ„ Ú>õë‹R\IQs±U ˆ¡ÃÓ0<Oµ8UV¬µ#kïqëáéóÇ1Ãܛˢ/ZS>eoH0N• ˆó­š·Ý€š'^GŠI»*Ì _9ȱÄéÃêY…î`íT+M`†æÅ;ð (ð„Ñj¹KUb¸žì×0×jêÃ/Áoµ ÀÒd:´ÓÙØ# ‡o>S7ÙCÐvÁ“mÙ4i<¶ÚÕâË3Ë´÷)ˆ„ßhŒGÄòN­My–ÊSVIF‹n:ÑJd 棌¥|”f%_û†¶µ¡½â²­´>ý¹Næ=á½*­Ü”EÌý½ÚsÀÑŠÿ¦³I/šÔj,Nø:Ä 2¸+8kŽŠ˜8žãmÅXå0HN÷$Êïçv¡Î(Ôåv\ÿØü$Ì”{næVkAܵz„”A­“«Ú©q€”@âYD˜«aM¾ÐÃsÛS`5æCW?¡l)Žô€«>ÕVvÏø}†·pW›[”«ŠBf ™V­Ì[“C³\4­A÷ºß­Ó5¬áé õK Ãû¼,éÅ>¼í4Ðõ[©”50ð`±ÀŽÄp¨Vʽ ÂoÌnñ :³ÉäÝÇÅ\lFÂÄËšq-•óè†ÕCC~%xV—iÕY,³$1#úoîEÒcî¤ X相þ3¼·º Ñm'«Wö ŸåF)žVûíòáo46~Ä\­ÐEA"j ôõÙ™Êw $_Jl5fgª¶ØðûvÄ]^Wœ´> ¬»åý ÓMw]¢Ú]HúæÃ×~̆¬h‰hU+* k?¶‡"|¯£Õ6Ïy‡ÒÈ3éæX´/¼û_ÙA…– _qe€Ö å[4–ÉØˆLÀZÆ&K¼Á¤ÙGÖ0ûžr ~´Èa7ïÜT”˜ì‘vbj•‘[\^ÓÐï"GNƬ¤é,òáaIÏU¶(†èÉå²—éçÆ²È¥ç_ûtÓ+Ù´Å”9ú„tÜ¥X›m¢wbF¿‘w\@•°ýLʱâU¬ZÅ©l: Ô"~‚§7›Ç1šl:e1¯À„™j¦uñ‘´þÔÍ/¥ðË;ß×›GPmzçû–ò‹É ³ÛráwZð2Õcë _@ç¨+a§ú¸Ðo0¡ 6µ=˜û÷0b3 2„ƒd—ëTÀÊ ¡Ûoc.BhýR\JfbH° •Ý8<·zFªNÍEª¥ûÜ+»‰   pæÙÁ+»µøÈíV#¯äØ­t-“Ûȡю—¡U>ñÐ’›-¤N'ÏJå§ì/Û…´&Ñ8+1œj*Ðoƺúpḛ̈Ö‘œÀ.” 0¤=ô¢“7 ‹‰~Å'ž]Ê«I‚¥&b§B1SU(!¤.«_{Èí‡ 3iy¦ ÎBRûŠT´9U…z„çq[›HìÃ7fŠÂ JxUTàþÉøâšÑÕùpü÷Q'ã` j2C•X‚Àt™$â—¢}œœ¤×àΣ͜´5•ýçUµ•/úˆ|+ÆÅIµmÃMUH»Ù#üôFäaÃmûƒîpYlP2)S~, ëÙ€¬pa±¶ ¶ªxÖ†¾{SÇÃUw(áÄ <'I¼l§õDànÉž)}—&Z» ¥=Ž,mœ¤`c/Äu íÑ$(Ú²FÜ\øQžŽjØS€Ñ1 §ï£y<ø$ŽÈ!å“qì˜ÞF¤s×{H²bLl?R9y,`V½ Œ"¸‚XëÇ€ãÙ˜Ý.L;‹B›õÄ”W±%ôÄ $½%”f4yÒuÒ®@I-[Æã©_`Et=$­4™-•ˆ¬ë%‘ó^ÇT#\%Úz`LBJs­`î´ËU½ÖšŽÅÀèÙᯫšÐ4Ù5jž„åÏj”½D…Ìñ°úià2ðVcŠÁd‘w¨,Êò !³3¡n^بœ¬J¨øvùNxÆAÙ=IRa]3†c¬ª€Õ‘ÊÚ{†Âêoæ,föfT‹]–&¨JÄ—B+{–üÈ0;;$jÒªø=Éf•^Çé›Ù$;úÒ.êi Œz ÷øU|YÚ™2@b_QÓ v7ŒÈ"S‹ÚzЦœÜæv¨lQÊD1ŒÔñŸsº¾ýù6’£¤ «]œ8£éhlMâäa¢êõcâÔãtÏ¢½äÄÑÙ K3› |oò4þWÏt É.š×É^6щ¸R3—Ö½°èd¸´òàk!ÎÙ|È &†X±dè§Läf O\ÉÀvߥÁü!¬-¼]/.º…³2õP™X &–Êè‘«ºauy ±Ó¸7ÓNΪ‰2BºS&5˜ ¤’Xù]Ùn‚!éhüqÖχŸ½+æ¸qeQ„?>é«pOa±¡,ÂB¶ètÒÊ™àA¨7‰L竎$„PxRÉ+#r 6=©J½²^¨SƒŒÚ¥§2Ó½Á~Dõxb?‚×ùè°¹ÅRñD3´ ,[&T° 6B b«•Šw¹;ÆtrìLC‰júÂÇ Xq Ê…ÇDej|²ÂЖ çÇuL§hUic_¤çã2蘸S0¾µŒ}šF*!™‘*™”Oâ;>=ÇÓ/¥ØÁçlº¹…ºb¹œ%0+5σX7+'ŽŒYµ;½å,ž×xfvãÆhñRþj5t„”çý‚2“ìæÇˆ‰J(kÐJ"]É ¥£HGË…“:Ù­A%ÁµÄ ×ExÎxí¢HHª‹Ë`Q.q¦0âlV—Ô L}$ÅÚ¼a»› æ£È·¤7'Ë¢Gi­3F¦!.di6w+G¼83°Æ$y ïæyüz d Þ0úÖøÆ\è¢m×ÁH¬dU°¦gÑ'¸R U g$?kM•vFZ òЇðSY›G{lg”Á„ Jú°qqaqÑËÁTºd³ñ¨Ñ……JïvúYXòl Ž¿4…(cñVD~xn<“5Ñ0S_z´íùÆ$•/FÏíZ=äÑóÍ/^ŒŽÀ¤šÎhz¦A†1ïVª+C!åâ”8Jä­DÛliÏÁˆ*ÑQÛç :êÚíeo³¢˜Û©i c”h\$™ÁAÒ¿kÿAYNôq £ewû8cî’±U ÆÎèi’üXëøx~ –ºãÔyr›ðs»Z•…éÕ‘ɸñà  ØÀÂ{•ƒ™<™ïŽÖ!F§ÕNnµóTÊÒ˜jÍïŽn²âÉàÔç¢Ìá|ø¦/°½ŒadÒ|Xmí)è›ÔCØ7I‚~Å]Ñ—u«EþUíÁÍ:C—%šÎ;%žŽ¢r ºv4‹H‚„ŠÒ¡$uLSf¹ .·ˆÃK,âA•÷ÍÕŠJ‡J-ÌÕR  ‹eŠÉóá= ¶Ñµ%!;0Ù}û11ÙÆ YŸ˜l ë.ÛšáLú˜*fÙm¨k^9Óuâ:] $æ›U0OÙpˆ§­5îvª¯1L½Å¥-tзùÈÄÐ=’Dž/iŒšÎzçÏv•`I£x£Î°Tžé_1¡(àÌ"Xg¿®.å¸-ˆ³=RX¹(ec àË£ËU(2OPè­@ϧæÃÓ¥ ‡z dº“È,"¨ç—K³Áµ:KÒ5¯û'¾¾BÍO¢¦Ú`¨©ƒ:ìÌ\“ú€–x;zux§©Ï`ñQ"¥‡ å‚ÜÿÖ3ºÛ‰ÿ'“"¿‹É÷ŠF“¡Ã‹êS™¨æËå«X†M»†ÂIþû$©ñè1%êœVL¡ cD ¢¼m+zÍ*ÃJ8óp(É)é:ì­ÜRúÁ“ïd wà“O±¹lˆí<9åߊ¤$ÞñïC]§ù*‘n.¸±tü3KfÑóÄ‘“˜Üá8n& _ÓMÚ¾§í…Üqˆ!{qª`ÈÆkІu+Ôbq‹ ÒœÚKù´,ôxcè6á©iŽÓc›âû¼–^X*J:ÖšM»H#+_Œ>¼|èñ{­yQ:ôj¦ÜŒ)Æ@6œYá`¤%ÙÃÕjó¦QÐ"2ôEJ åk™léaßZF¶46Ä#OCbKõEŸ‚rµ©R`ß³ò:¨ý!°RQ®ò¤ ¤ÖîÖ{,Ål)ÕjY¦HVH²/Ÿâ†>E ÷žR("ƒ”-.N*¦õ–ºÞë÷¼s¯Aî V‘(½µ “Û¥}äüëôTÒ3Ñ'y`` ÿ #n¾>ôÿS Ì̲~ƒE±;÷]IPèJ!½B-|!nò G3ÄôõdÌ¢B™(IxZÉQ"T„¼¸·Z\ƒRÌt”]¤I<1]}&yi#ã›h: +PZiP¼™ N_xÅ.š2–Xæ@ µTv¯8D×€„; DZÄ¢>ô‰ÑµÆØÝ¤×r‡C•! +2“úÂw,qdéQþBwœ42¥çÅÌË\z”–GËÓçià+B•ó8U±@ò‘ó_qô¢K£Š:cò8öØ,ìV{ÑŠd’ 6:`‰5U­"òâ5cˆˆ´)®z:³ønoP/0I üª ß$QìGnŸb?éá/üާÈoÓ‰³¼™³5ž0Ï›?ÛãE§/jš5w}ÅEW¼SW\Ê&¹÷ó‘ +4{"*®§9•üqIÜ£sƒ`Z §Sñ [W½žŸó‘ÖzYÈ]ÐA&õÊ«²<¾ŠÄÓI§QÖà2Ðù?ì@“ƒ¡ATçðVh|PFƒt»¢¾)0Qã*‡• Û\Ä`4rþ¦cÚ³1aÜ“g‰JmKÌTKÆ!܃0¾ªŠµhÃn!;—tX!—åäšÛuXE›J×ÜŽ9Êì3ƒ³š»/H“0ú­ÖK\½1¦“CJó³¨×äÃÇÅ)^E÷Àòž>V¼ÉÅ„¾|µRˆ\ÀÌoT“8±ªU;º‹hDó;˜@1Ü鯲®kr¡Ûàu}ûJS'ˆ²nUµšFÖÖ|—¶E™ˆHÌ(Lf\zráÃÝ­ ëðÔ½¹º¡èó°XÐÈFøæÃ] ¿rX/*_¦³ùÌ+¡;j;ãu±:DŒd$T„×ôxE¯8ú•¹…2¼ äØÚ”Û6õ~PÁËT½ÑïÂ Ñ lùP@Ä ì›åòzùé³ñéÔ“_ñüË^<‡ž¿ËƒüüâMUEJ½£‚°ÙNm †5ì‹êâäUn’Ý7(+{s«?Aï>öb~· £Nµ(uå²Ö»Jú¹î˜W UA=L¥f:’9.˘dtG* ¬£ÂÚ«æ[æC“^Uz»ÕŠ`…0õ:âÑ(ðŒµ#í.申z©ôƒ’ÙÁ=pÌØ_j&³æC,t³²Ö¸Í.%8ò""Ï‹n}M_è•C™5¾S4„žªå­v0Rk£J3ë¤e³®¬T¸p×pÂγ"À©Š˜_\C–P±¡ÜÌ™ÅP5ËѲ™i¨( P4ØÄä£G\ j„GòרxpŒa…äØÐ¯¨ñDº˜™h-½VU¼*«ªî͵íáÓ4<=Ê[„çÀXm×òÌÍòÛ:á†í\q¹ù=QK,°–)ŠJ%Véu^ñ€Z«ËZðgÃüÅYvþ¿D^¨I–yS¯¿X7ÃZtö `?0Vtˇ^j#͆4OعÌX‚J—M'­\k/b³ áµÊ wÒí&¬<‘7Þˆ9<) P—Ûé¨îÅnѧ,zq@YHþf¶úx¶œb _ný2YòcEÄš‚Si¯XÓöYÏÎfR§f¾&YÜ*ƒÒpPÇ:SiU<ÌdA×YP\‰s_/¬Ìžß@™Àï^ßD»ú–Àø`3øÁt0åùg“ôê›À:7|Ù^:Þ‚Å ˜î9ì3Èô„D¬\ËO }°‡À>é½#1î5¦È ’)bFiyOv@Wªpí4Íð«}×ÓP!K)¹ZÂ=çÂÄE¸ Q—’ìÂ1†ÅA;¡ì +£Öìx¹ðÒ‡Š7½•ÍŠ.}(CXsåT­„¢«Üϵ*Á!¦á”Š¢Ë‹Ìô%æ%<=p"EÝóá•·FS\­du f;ád‘Ya›àðé„)cŒ®‡ñ™‘»âè±5 ë5´q•È9ær¦˜g¶*3DÓì-êoïº:)%¥ý}˜ÊÎmZ¸–—ÓÊ­¥U‡…žV•ˆÔˇÓ÷ÚJXšU(P‹„˜d|S¥W<×ñ ²*V0xüÊOÙ”*·‡ve[ñV\éRœWË^qö€tGsDúAÇ\\ˆã´ÄI³} ´9ÓŒ¢×Í¡EK.-0®çù¡äÙÆÙvf|íbÇ;?]Ä¡ÔÂ$Æk Æ¢D¥Sç#û½Ï(o¼J0!âëìPQˆºÜ°Í+õ¾¸ðZâêã±/–úr*“^éñçl™oôSÐJJU3?ß­¬æýH ̨=“Kt 0ÁB½)?£»)“áX;ßç,­žÜ§¾f—Ò1:AËûfKAFÂô¡¸÷hÇbvÄsP±Ã~׬mùÐ·Žæo–Q>`þk˜ Ø Î‡âýéè0ª*N*09Þ-%6Œ€sc(Qœ“•DÑø,4•ošžUUbyeãD"¡ NœDõ‚Fk¼jfŽ8ª ëì]£¡6¡ ?‰©*.FGæ%¤¦eEÍ`Y¸$²kaÎE»‘>¹ÃÉ]ò¬‚%¹ÃUœ `õ³¼ÄÊ17zåeœºÊncl- µÒG¯ ÍqJPru¶w¹…}sòƪE1›²ÓƵ‡»ëpš$=3…xÏãÔkF–³Ÿš¦„€ÍŠ¥a6c&Eäô¥A¿E œ‹j$ F4UF3å6õæÆµ[AºXš)Yl ¬ÅUµ}?üŸÝQãÇ”š´'c5,–f}¡Ç÷ ºMÈo‹œ­1"ÇÔÞå|ƒ|DFV\R¾^RÚd¦§vOáÚ»;Çk¯TžÒòYiOi#Ì¢.§=æ×©É…~ñot€ù`Ie[q99¾2"}û~°ÔóÚO ê+[öl*Râ\L:Yš ©U×0ÒÁ!µk¶éEÔJ5ƒ’ðØDoî° ž s*O£ÜÍœèo‘J¾ã 'h°7Ï6l„BÃVÏ…›¬h$ÉÅÍØ4àKEhýæ7õÚ¶üÂìäp•Yù"E“—fJ\·ÔŽžžþÏÎÜvg}o¯ÊªœžB¨ÈʪRavÀÍG‹r!w£åŽö/õ›`o5…DB’û1÷ À¨üZ]u펴£— ]ò—|ˆ±óÓfíhè›7Á¨ÄUTD•4 |è¶¥㜚 ½á¶*YÔ´~ŠlQ7`µÑ¢oÇÒjº2ÇvF ëOôVñ¶Æ†Œµ±!‹ìtÚRLCV­ºçÁ5VX#~¢U¡â˜¸B!"š5ÁDæÃOßb™Œ`yÛ‰˜uNê%3bù9‰&p,¡| »Pþ5¡ïOB U*²à,Uö7h´^AgTDj÷nR©ß*¹"襋 ²XèlÄp"[&ž@~Yº†D§Ö#a¾ Š ç(T/ ‚¼(TýE'-Ñm” ì±kObz)^,L'’;ºð‘ÞKÚº-|š ñV‘FyèdiC<ç–sUH‘ÒÊ aùAð1Y)MIVŒ%9¡\’©9YSŒ¦…CÛ×q©0,׃D3&»ÈcG5†TºOSÙw‘.€îÛ¡!¡Œ>Í) »¾*Q˸ô|xâ \40+”:} ŒÛ¯ˆ?Ò ‹£9eÒþô‡ ±kÕg‰»Tš?‚ø6‡.¾np»0Q±‚Š@ƒsßšk®Pƒ…ÏÕ±JËEMl«Œ9½Ö•6Ñ‚÷À¤ã¶•õlâÀ ÊS¸D^æ• 7ï´³RQOöäŽÝ¼q ’ÊÐWæ÷ÚöþôY'xk*›uiúJU=^ù+_?{?°[)€‰WYÊí¶ù£5G§W:‰lì8ö£VÙO­žš:ísv÷VÁ;«§ê÷¬bZÊÅ‹ä~¯ 9nÅp'麬6çÌ@ ã®\%ûܨ½Fo ê$ÅÍrªîƒýMÈCÄQvŒuÊG·$R­+rÃ/øtJ¾ »ÐÍtfÎ"/Ó¬y3sЯkލ÷FyGŒ…Á#aà`ÜZôŠÃ¦ªogh ¥Pš´Vl… yÂhæbžñdS%Æ“SþŸÚsÄqäå?¢¾æˆ±52DÔ´êš#Æáxµ ƒš[›Ðc!N\xi&•-ÃCm §L£ÌŸòzTùÚrZÇè%)¯ËÐg™©sdt–ïý,îx¤ à»°F›þAd“’ÿ™Òl B_V~]9x¤›ª÷DcÈ·‰œ{²)*UAo 6bއ•—·Œ`±’\uŸÄ?e­‘ßD­U»0WzT9.SH‘5ÁV=i}ÅßïÞPþQüö“ÖW|ÐôCê¶r“¦þöµumíÁ“½ñŸ‚þõQ>ø\™é•" ëÖö?ðɾW>yOMèùØÀð·ÏG¼°Ó¦ªÚ~Ö?w¼ñâŠC¿•Qõr¡ÛñWCèɵôIÿÝ•?äâûíø~¸´GßÐÓÿö³{×Wü-|¶yˆ®E— Oéþ_]Òh>[ôú!Ô7ã9®ÅpgâshBÇ™gºÄZí5Ÿ›ËlZûÕb?ÖâmøÄªÅ0¾|-‹u÷á_{Ü(¹rnß/í›õCBKGÁSìÎÙ¸mõ%ïÊS ò-9n„R`?»ÿý/ŸwÙÅýæi¥À~öö?ñ+°|‰×_uqÅðgγ/s¬â®¯øÇ OnÜÖòü§¬µ®ŽÜjjVV{úÿÕºª7·ê˜&£¿j®î5é¿jxÛÿòùdœTe¿Þr—ópÿ+cGñ}MOìÜŸÞ£; §ÿýöéÍ-ú¢Áô‰~ \ÍoùâÕo>Æ'eëÕŠåL‘áz×}ß÷ëÍßí»n•n…ßOyg—×øÁ=wîSîc×W\öÚœ2_ —ÛÏÙVýÞÛÿÓsÖW¼8ù„ÛŽøîWìrÙj”_LtÓIž ·Ýk+^{õcÐYg¦Ù±oˆ?lüí@v(÷ØóìÃ^û¤î!õréGìúÂÏÕ#æëˆœ}ó¶ÈÐãä Éál½NS*Í_]}ÂC¿RW+]²YŒí®º~ šìü›`¤erM=ìi}îÏÙä¿ Ð·ðoî[°³zsÝÿxOŸ2] W›§˜Y)7«é!%㣲¾âé’EøÀÕ×ã9µNñ’⥌—À9¿%ý¦fö¹wÔõZ'šÇ/ GÏ>6pœØxPà8óôãµ;¿l¯¯øvÃÁ=«® ž¸âÖ‹‚'~ôjkðÄ ûÍ ž¸mþ‘Á÷~{XðÄ÷½<ñë?<1pÔMÁÏ6?xâåõ+‚'Þ|tNðÄÛ_ÔO|<~×À‰!ñ·ƒ'vìÿmðÄמ¾3xb¿×OÖàOT¯j ž¨¿uBðÄäW÷ ž˜¾ïGÁ'Í{.xbáÅ?ž8ã¾ Á-ÿ^#'¾x®ÿ‡4yÇfîð±™;|l曹ÃÇfîб=wä„™;rÂÌ9a掜0sGN˜¹#'ÌÜ‘fîÈ 3wä„™;rÂÌ9a掜0sGN˜¹#'ÌÜáÖÜ‘fîÈ 3wä„™;rÂÌ9a掜0sGN˜¹#'ÌÜ‘fîÈ 3wä„™;rÂÌ-xÔñ‚ÐIãGl ãë3Ç“{(p<¦æøÀqÕÄ_Žm˜8Þ÷ä{Ç_;ulàxÇå·Ž+VÔæúÇÙ›Çÿ¾ð¨Àñ_¿]àøÏWZ´V~x¾Z\y»C'°G'°K'°O'°S'°W'°['°_'°c'°g'°kìÔ7Ø9Ø;Ø=Ø?Ö ÚË6n[~ÄÒ€:›´ÓÒ‹@3¥“TIû,ç/Ù3೫}–ÁzÚ%|ùª’§g{×ð²¢FmŸ•yf{‰•&ØÄJ³óŸÿô/4ËíÔ´f‰—J¯°•l©¼Qpp`†ŽàJFÁDGŒ )Q“ ÿã&'Áž‰fãÂðcð– ú TQH~‹|!˜¶Í±Úbge].òË…\ÍÜ‹%ÏN1ß,WÕ¥RºVÈFâh¢Ç¼nâ5€á'u§¨˜6®§rwRÌPØ0Óƒºp .i4m¬½¿ú9#oˆŸµ Æ™“Æ1,8Ï|øòkœ '¨ÄwÃ\@ªà¨€®2ÄíéÚ5Raâfœ¸úns>ôñŸÑ“—&Œü9YòjĢĿJóŒ”ZüÐ,â a”v>3fÓÂ`ö eäŠëá9åN—Öç#‹ÿiÕ$Ú@„á;¸—SGòÍé%oÏÏfä ¸* ÆDéÄ·èLtãP}ØT:^w­TZÂk‚ÏÑÃÎyTð‘‹þÕÿRØ-p€‚JòNô´å#Ý}¦¸b1¢¤@™èC`̢•´ÃK`Au/`t˜p93µŒò×#ÙedÎëšYõHªMO¼6\ŽðŸ&câo·”Bˆ%;¨DSüÈ=äĉbHMáßGî!ü‡jóãÆñå~ÔQîлi(ƒîÙ§?Ô4gR Ëç—tÆ]—ëŸj,yïæyŒš‡þzúiz¤~±J|'ìDå²!0³}Š:¨‡IhP:\ÖX,ý(û]m伤 JÊëÉ,rÛäU}á§›Fýd]~ÈßZçÕyGöŸD=–„ß3¨—®¯¸ùð(²_‡k¤b 6ñ¯¢O&Î.fKÖt‚áRt éy·|ŒžƒCøÉY%™É¶/F‚©g2›G2¹ñ<|Ì*ËóÙ°x3)E eãt¼¹ÈG2ë®púJ-i5§ÄÁ“$ß~ôeå$¨Ž8´.ïŒSÅÕÜГOGådùÀèÑ…‘òHòõë‹`éâL-±-o  €•“Â*wA9Ó œtT¾£5qðŒT×·Mî†)ÜÄñd0/<í7ˆ"‹ ¿Käˆö¿w:â{·œê¥À*.d WøWXÖ?]‡µp•ŠÀ™§¶¦ºün•]ÝÉÌš–~0x§ÌM UïTN~\œ=O_}‚4<óúHx&<òIãj¢øù!…ƶ|èÇc0QAó'ÁÚcP–x1tÁ·ªN§l5”VÙ.U#†‰i%4zöÌxT2#(‚ãbX Ë3%Ô‡aê¿©¤Üj¥e&$-“:]ÊÁ ýGö¡LÒdÕ÷¬ y2‹ ž^J»c0K½ÛlÕHW¢¤Á¤ÜÒ”—g×S>˜N ½Iv9 ˆ*:wȤÜÖSiMzÕÊÖÅ#š¦ Åó¡ž/$”¬©hA² XWç˜ì’Õ¡ —¹^ ÈR‚CøzËñQÂ<òiÒ?^ôŒP–Ó<Ä8/Ü‘Œ1ðÏSé “7†@/èg—D?Wü ¸/•& !64èî‹‹öÃsŽÀŒÜ>xH‡ƒ¡puÃ'Û«àò} Ç¤„ ndªK‘o€zÁ (ñ3RÝäòò¯5žn…M ³)˜ô“ßáÒZ“s™"oI+po!£ÕøqbQÕlŸEuÑ_—š@q©Ù‹›/œå-Á"F O^_ñøŸ¯/Œ_Œö£™Ú˜lMd£´ÐAs°lüI:™®€Çc òòR{”>é…G§Äu}Ø_÷üÕ½¿’¥úS‘p´pJBhGð£kßÃm7ôè冱oƒ½2Q×vtáR¤J“ö”ÄN\I—$ÞS¡ÔfÅsk„Ñ Í6±¼›~ý~sŸìÉ´ùö%'6Ι…ÈôØê®´7s>¢#ѧ‚9f¿?€XuÄ4f3t®'7êÍV+»aö¹5›*z{{ssò×æÑ RɼÁÝ[‰g<€JÇÁˆíL¤@ Øìg;!o»@ ™‚•«ýrÍ|Ü5Ìz%Þ‡|äà'…è›@Á4ò2j-\L­eªc¶"­|«v0ü¨‚ªÁ{` a¦M,7í17¯ ƒé,É3² .5‰±‹wr¶:)oȳ7gTÚ¯¥kÁH–OW6#S…ÝÖËŽ/°Ï%úè›L\¸Žë4ŸL'òÜmlœïøŸß7iTÜÕè{ˆJÙ»8óöÐ/ý‚Ð㳂¹ñ‹zcïxѨ—[¡Æõø,G…‘•ÁŠð§Wµ6ÃŽøFÏà,=ÍW!ô•TÎ`®a-Wæ|wQjPsáÊ\°ÇÞ†ð¬’ý’DX.ãÆÍ¨vàůiJ|ÂÈÕZª87?¯.aª#N#¸„KÙ©ÐZ” ÇÝÉzý»½2—ž|RÊ¡Jìñξð¬[Á¬NS #ß͹0Ó†2Ö öüÝŒKamB29KlºáõImŽé%`Ûis² C6C³Jiî¼>~{ÚÄŠâÑ/JÑ<ƒyÊh"nØÓªsC_MP® •²Ì½Wki ² ÿ±XJö0\×Öøˆ¢ÑWôµB1À¥ˆ`ZMüuS šÚq4¼~ñb½[1܉Á@ m„ö‘'W®»mr*…¢õè…[;»”^_ñý7N+TõåIºèãMáBÍà#Ráý œþÈ»o-UyP¥ Y„¸Ó©„E’‚w¹ßÑQ,@å2&½ªÓ ¿ÕŠþ¼4õ<Ž.-zWÁ´‡«æpê[·áÎ/ËÅŽÉCìBum•G`£¸çÆ\]nG¯:úã=Bß/QX¯¢ï–„_¦ÊgýʵÕ_%4¨fÏaŸi>.M¶ü_¨duòÐù GÿöŽÃv’ží ¦xJéØ*“G'ß2¥ºä-YÕÔ(Ô(‘]«Ë‡æéÁ+òÓôdF,©ÅFÂÎâ #ˆg–VUâŠÆH.Éó«š•c<|òK™ô ¦âTN«Æº*ýèçM‡"hd“NÒhx´Ôb͘4Ô}¶´uag mÒöÕ¿SS´7ÂGG=Õ0ý(cR}F¤rºfRGœQÊfPýuïߤe1Gå#ÝPUstØÂ€Èùã8‮b¬YÕ!®šâ‡v)+*ÌùÈ¢{ºT (.¢Ø×èIpLª·¢H7 ¹Ÿbü§„4_ÒÑÖ©ò’ú|dm'¡Å ×1¢¼¾n,ÓüPÖãß/¥l¥„|²5¿$SÎ"êF¥ ô(±êêãl£éZïBfrÑ_y™õœ­¬€µ[9~R(îcº(n‘ÖæÃ¿ÌÛhsØb~z)S0}iÓ;Dˆ8QqøªÆe’êçQI+CùD¼íùȉ[JæG e/–”I(ÑŠ`Õ$Ø3ð?±¤!}VWj¼½uÑŒ„÷z曇ޮ(ôÚa÷c-{Ú’a#‰sªúœT"t=Zyë¡>æ\ú4Æþ„ºzågÇ:><Øã'¨·ô»NÚW§ˆR›ßz"®ï¶i®ÃÓ.ãaã*¢§$ܘ.ÛÏâ#dŒ ɹȟ Šk,Iú.Ìñ(™‹ûÂ7VsÁ;V!™ ÚaH´zì7³ª¦7{·Rβ&²Š›ß’Ȧ%ù .]Ì%‹›P¹õ‚†\øUd­<°^jGö…Ÿ{…‹¼ C¦²Çh'ar\¨OҺƧ(ª.’€UÀ”¯ÔUðÝqWÂ^LôÚ˜a/`LIo‘ª*@#I1º¤f‘¬SûÚís3]žüoÝL èyQìÙž_üiü¢ï?ÿF§ÃýqýO7n;æ®c/£4Z1qL¢'÷ØÀ®Þúä-ôöòïý¯ïÿ™õó‡ðs-C¾u³¿qÛiáó Мî¼ce&ø­—§“Óô5ý?ïùcéý¿û÷9(܈ç辫ߟß–ü/:H‡uOÞiMüýÖÑñÏüÈ:šýGÏ:š÷Ò÷¬£S_¹À::ó¬uÔö÷ÖQò_Žu´òÝ%ÖÑùÎ5Gë+.ùt†}ØûÅdûðÊÐhû°Ø‘öáðoßuwûðg{ì`nÞûsûpË~ïÙ‡ýÍ>|ö°—í×|Ú>|³ú ²Ùç߯SoŽuw˱îp9Ö].ǺÓåXw»뎗cÝõr¬;_Žu÷˱9ÖCÀÇÖ ¨zÔ =ê„ uB†:¡‡CТNè!Q'ô ¨zXÔ =0ê„uBŽZ|ÔÿÑ[gÚ‡o¿Òi¾ùüyöáË¿½Ô>|vËûpà›ìÃ-÷l²7ß²Å>üÙuÏØ‡·o°'Lÿ¹÷íÃþï…íÃ+/ÜÃ>¼|Õaöáw’csï‚Ø´ÀñªæyãÔ¢eãö“ã³ÖŽ—Lú~àxþè«Ç'õ“Àñ´ƒ~8>f¯_ŽGïütàxdèµÀñÁŸ¼\Kcµôž²ÆÓ>ƵqDícRûÇÔ>ÆAµqTícVûÇÕ>ƵqdícZûÇÖ>ÆÁµqt­cÞÀ ßÀ àÀ áÀ âÀ ãÀ äÀ åÀ æÀ çÀ èÀ éÀ êÀ këDOnìè‡)£áõ×¹k9DÿúŠks3Ë@úárû1îw›Çà}1nÔü˜×Þ|\=FÎ ò˜þ§nøšyJ™LyJI*ŠzÊÆmS&Ü„9>ûÔ5²Ima[©óâ¿ë•ü£¸\ιW0Y :ITUoŸ“±ˆ™¤·ý@VBÂþ88U÷ïšâS-¹ê¸SJ®šùÍ’«N.”\µð•’«Îسä*gFÉU™’«R×—\µòé’«ÎZ|ÕúŠoO,¾l}Åem¥×yW–^·aKéu×|\zÝMU¥×Ýqzéu?û^éuÜWzÝ#/½î7”^÷ÔÉ¥×½p^éu¯ÜRzÝßþTzÝ;»”^÷ññ¥×mK–\7dXÉuCv(½nïŠÒëSzÝáNéuGçJ¯«ÿ¿Òë&½[zÝ7/½î„E¥×Í»¸ôºÅw—^×üzéuѽK¯[1»ôºôÊÒëºo,½îÂgK¯û×]>©øºÂMƒXj~j?,]ˆ­F¡`*Sˆ¼ÙköG=å3·EÂz v܇¦·°UòF;+‰,K®ä|Õ߸W~dĦ¸¼7á“RªvúšµïŽ‘¯1\•†“G}ì\ØC×Un5Îal„“hO¥a:店ϻLžÌ0¶áQi¯Š"~±Óª´~H¤¦ \7\àÌòÛPpªÅiõ©°¶Ý3ë‡ì|æ¹ö}ÅwQ¯üCÀ}œeÛûþ¤ ¿~副Y3¨g‘Ê(WŽíº‰׃EÛoq:“çvÌt²4ØE¹5ìD¨Û>'Â5O—Aÿ?¥Qþ ­ùm“>X‘Ly«±h;6] èߘ }°ƒ‰~p}‡“\á$%ÝãÞ¢V¿ƒ½=ìÏR¼›Šæ€ùdÝ®¸Pá)Ö-7«'RÁý7$ÜT>\1‹^C>”Åu•{KÇâ„¡—0Êû ¢5õ²©,÷¥ ÁiÍ`OìTÊ“!¿+<Ä5)÷âDc39CØ_.h`æDä’}Æe·j&T¢ÞÉ8³XuFHTƒb¹¢éuÜÑDËÑÛ7–…ý¿|,»ºr[†#ÑûêÞþ)rþÍE]ëÜqvÒƒ! ‘¸“T ä1IÇT*R^vã«Û ›%âna)0¸ŒU¦ôޤʉ8±š¨ÈÙâŃñ1(↢€þ#'J@_ƒ,U49@ùÛ{}Y".¡ËÓ\mæúÿ‡ðPÙ'G¾¾± ÍЗa> UÛä3¾Ci¿Û9nç ªí¥Q?‘zãU}ÉxÂAÛØ‘ÊÁ¿tÏyU*HÜs ýRý¿c.j‹OX0§až7³»(:îˆ gì1Uc«§Œ;fÍø‰5,Üc-é,r‹ÔOž<ñi«‘f/+­^@«=¾fnC7݉+n\8Zä$8œu£.7ô”E ¹ð5“‰Ü•H¸äZŽØyLq·5ÞE䳂„Â÷)U+¦šD’oo]”jˬrÒ}Øzü¦ó`k÷)êǼ£¼Y«±: õcümõã«ÆUO;nš±êk¼¹Nšk†ÕOž4^0PøYãä³ÖåCo¼;?‰JF†ïÛÖ ½ñÌ‚ ÒŒEC°0VÔ>›–ø Ý. ×}C@¾¬dê'bSëǬ©?&ØÐz«¡ã¥¡'¡–xÀ«ÓMcéÛÙýäj€t+'pÏ+»ú[g€öšMr;xOÉ…ÏÚ•)™à-[ôÞlpÝ^Ñg%à ªi†/™ë´"quº[fÓäª 0›&Ž_3nâdüJ)€Ï˜h}ÆùŒþ?¤]}[ÕuÇ’Ö|¦¦™ºI'…¶@ˆMµo%=}Ú…ŽV«õîz×»Ý5ììÎðÿ`¸ŒÎ?ñz²D5証2"*‡]òìæ“¿»®â@¤£}$§ø6‡2 ‡2AĘY³x,åLÄTºbâXâƒr©qÍS8\É/-YÚásûýÖŽ“¥1|²á{â±Ñô=ñb?îàuÙáà÷…‰Õ¬¥UòYS3sµ-C¬ÒÔÐ û±Ž¿1ðË9 ­|ðkKyöHȯ„hc€ ¡»ß޹ড়H ýqNÿðCò^8©B~±ŠKv®ö6›\¨štJùk,ü´ÈªáHè.‹f±§$¶xD¢qªÖ" ƒú¦ðæ-‘x=ªûí$°W:®šà„nAñîDª\ªð"¶ÕìmÀ¹EpôtÇŽt'¿3=‹¯ŒG’IøDŸ™çORq!ä©¢3¹$Á½‡“›Ÿˆ>Øl$ÙÁ pn4QÆ"~˜³„òksÇNÐç ÁŸÈ{4 ¸ó*O _|19Žò§fÙÃX2¹reÓÌNz3ÂødPåPæF.¿TdâdSO¹DoŠÂª†êÑ ž*–D-¨#tá¬êÑLª’ÇÒ}mïÁñ9gwÝ‘NR/È]‡Ÿ;¼aþ´G‹­VTBȕ޻—«¥ì9‘'”^jo….¯Aˆ|ó’O xîÌž0Pò —Ë˚ݙ˜Êr²õ鯻¿V«Ø9,BM‹#0QgãG­›¨€b¬$VŽ ÂÛ9Fgߨ­ª‘«âÖb¬¾,,Å´C©Ðc3M¦Æ>6jƒÍ³EGixwE(;=¹+ñµ ¶jYðµà~¬´^ȳpIø¶Åƒ7ñîUó, :àm,qœßv‹n½MæK˰0~X^¡r~sý †b!®«óênæò?÷m+rVÕÌ£$Ù9ÓhA‹˜·1#MIÄ@ ª0*NîG€y6€èB>¯Yas5½¯‡b €žŸÒƵš„A/¢ã,D³PÈ/QÚýI#Ó*“ý!äÝÆgSÉk`æ%õ ei8Á˜k‚‘.<õ}Û€ŸË¥²Öx`lº6;NC}’~€Hlñlä;ûX½ëb>[.Pa€ÒéŸ!?èê€a€€–ÂE&TŠ£.ŠÛ¾K–ÅõO_™bo<1NÎßôMS!ñ /´‹X}¥b, ‹úŠóêÛþ·§;¯!‚p±D=&Uh”pá÷x˜ã÷k׆߿}¢7ªcx|xr|zÛlrfl×áu–ç:ñH¿—B7c†ñÏ‚äßúÍX¤£6ðÃoΕ‹¨Oy°†fґͳÒäŠ4£…LÎ¥’“ ïñ´Üµ³Ãð°q € !„ öœ¹Rí Ê3΂Bá&ø7>Òì18%ááÿw ù×ò€ïoì*—@ê£ýßã“üÕð}bÓ™0.ƒ5‘@=÷Û§Æ4DcB‚­¶gáÇL é^Æ“­5•e§;®ƒ ŒDûï¸zpBaŵpéwÁšÚn˜…LJß¿j¦o\9Œ°czgÃwéŸÊ<0€xèÝ¢Í L!1¿f î /Hå2­–òU¸:qÈz9­É´Æ ™jö¨fϰŠ"ëß½|€þ²À¡äl>~*¦B}ºLÃÝÿuÖ¦apK0LÔƒA<_ŠMN •ȼÐMßÁ¢w½ý‚çÕùôpÃwðëë€*ɨ/ŽGZ‹ðÝ\Õ@ï›]Bˆ5½³ÌeI•سmÙ©98P€hgÿB|f÷1ÅZ¢ÑßJ%SÀHÄNb_]âNÅ*¡X×4ºÕ5Íóž:óløžÂÇWÛŸ¯Ž.dpIËvyÄ­ï»÷µÊ˜*ÆÝC~X ) ­& €½Ï9{÷AE a;Â6Jærx—788×´ æ›öiŒ>”·Ø |è]­bþ—ÞÅÝ3ò¾u”fÄ.@÷ŵÉþ~ò:ÿÆÅ‚f5¬%ˆ³ÛøëÌŸ–ˆÕ… 9p®°JD¢‹í~ײú†~p¬g=Áž¼ã(.¶w%Íx¸l/Ul£x£ b}a¬á†WûŒ{}á›+ÎÕM´ŸKúU·ÎE¸çâ9z©² t|çò…}ù2¨Æ}\9{o{™–Ó»aK OˆwÃÇçäö{°“ƒÆ-#<6Eð+;-~<¼×áœø³@] tH4Íd*wèÒ*-ï-5=/Žo¯  Dø¥_YZÛž7w6ñ?o¶÷YšMou6%Y9r0÷xÊ¥é†ÿT•6Ó½»*¦´×ØÏÄN"°)˜ØÜë”UÕ¦R|'i/Çþ¶ïÞBg,Ó|-îVcDKb(Ùö͘Wž½æ5³µ.<Š:_ÐDÌO)IÎ ‘Áz0éIt¡g .5=¹ÛA² ÐÔö¼¾xÌÅÛôtÚó­=3»¼Ï¬d,Ðícd¡íØö|öë³$D1‹PÁlÀp€]*ËþÖó&ü¿ ßt*ŽãÉLÄT½¯‡Í3ðK óH ½šÍô®^kŸÿ¥ ÇÔÄûè#.ƒÐIŸ/(`¸9 =yhÀ¬‡ã]ÂÁµ¹Š.ôÝ…¦Ìsp+YŽ›¬ÜÓ^ªåñí:©=èä8D¦û’Òð¼öÉ`-¾X ªC´û¸¸Tõœî6ýšžÇ~6¢±š‡[¾ðøcÇ»²ºÙÜ×Qd.;î U`¯EŸv£uãgŽô-Á¨^‚­ÎýÜ ¼nmVà Œöµu¡çó…BÞ(6½Ç¡Le·›&ÙO>=™v(ïëtoz+ñ.¿^Šo‰FA‹HC0s5àµÌÓß“dMFnL1“7Ú¾W¯˜mø^yrª Õ^:ÿÜ3Ý^Åü„¾Î¾@_i×}ðô™ì:»&¿8ê*¨Ó…–Cÿ„Iæ¾¥F ¾øÕÚúß;H†¿‘+€Îä‹"\Í‚ t/¤Ô§q”êxæB‰D]†•«‰¨zäÂåÈýÓ×À®ä-°™Iƒ —Ìõyö ”pýßô^ñ:'áP"/sk$ÙÊðûžÿþ;r/‡xæ™wEÊ!$ Í3bVÌå¦ï7? 9W h’Ÿxµ×÷¥Xá ¤Üé8%‹§åhúþ¯&*­rk NÃÿ“ ¤ˆ'C—Ž5)aÝ‘îp4„ëÝÐݵvBM`Z¢¦÷ŸaR#)…;NŽ‘õÞÜ´ëe¨ð綺œVØSÎèâÏÄ!ò+Äõz<Úϯ j°Ð:°«Ï™…_¡‰¹ì¾û…Þuu|†9iÓ[³¯S&2—¸ðýYyÚÀ¤‹…ëè°ïï°q(z‰9eÚÞ#Õæòò6Ök'æm“ 6Va»¿q š ú ßÍŸïÒÈÏuó§‡pJ íIå÷–ËN G\Ójäv±i1`xAÚìwßPE÷z¹À²T±ç¡,Û*Òg³ÒHå¥9ðÊýFÕ^]¬®hYKÃÍÍšx½dæjvvzu¨b®@Gk¯&†ôHP[±´ë;yééǫ̀˜ †Ýw°æú÷Îcã­Ô2C¥òMfF³öíz0C?†&øhv5ü–-WL ¨ÆßCò¯p5\w’©¹Á³ƒ@Û`"èo yoÄÄ@ nˆã)’ö‡b ÐH¤í™„ö³ ±ƒtË$B„òæj™bžçØÇÆÓé4r²jJwÔÝ耇‡a¢€lÓûæÄlž=Á­äטôëõï%Þ7/¯˜EdX–TyAJ‰*ÖY]ä1yy ŸQÄܰÆ{×[;4{¶\É€J'$:ð‹&¹ïŽ ÕH·rçôÌÆþË{ÿ½¡0ªhT؃±[nî^wŸ ¡ÈñfüŽ“HˆÅ¢÷&lfÂ,t„}xå¨-Cü¡gßd@ŸÛóñÕÛÿž(èh4Ñã÷ >™·Œ¦çÑ—`Sgk¼žñ^ÿÈÜöÞuÿ K+$B¤g )½Å6ì‹*¢øRµL÷aTrÑ:€Žý‚‹Å ÏWïA·]ÐŒwOq¥ç¥¾ÏóÎg€Ûù €ŒHcj#DÀØô»zé\z0Æ:ùvB1€ÅCŸADÀôJýÉ\–‡)êyí¾­•Xõ®µ&Á<‚ÃÌî>¦´ÖÜÞ|‘t÷.››†ŸHήÿ›z+)4_립켈‰»‚{`N·?@¡r˜H™°P4 ¢éKÞ#kÚóOôqNx¾ö6蜯€Y(vº±é+†uhzvŠqpdMI{ì9ö«#,ê%kZmèÅ^ÛÐ (myøô œ8ügŸð3Jg%½‰˜^£=²–-žÖüO¥(Ù5Õý"n¡ñtýùB·mÑZ)fÕ2b|Œ#EvæñmÅ<¯ÜÅŸ‹èuBr£›Þ“Çæñg –”s}hyœefâôJ¹ÀRLŽÏÍ4¼'ê ¢ï$¤ùµKË6\,Ë©-ƒŽ·Òcü¶&mq²)ðA4.ò"ºÔë=ØÑ\ ìÄ:¥`fŪ:3ß·ž¿Væ®-™7‘°ƒ3ĦT,Ñ”>Çr„ŠYÁ7Ç@¬4½|œÇb†ã ù¬ËoI‚{2a(V×Ã×E\€z¸d Õ>×|•Y@èÅw=3ŠÒ°¬è'ƒÉ +Ÿ²Z,Ȭ†÷ÒЇ”4ìxÁôfÔZÝ —ØQªÝ¦ïGK¤¥YË" z¸ãolýJ×m6ô›ä£û[ò¿ü+ת{™bÅ[u &ëü'›,·Uç×f«>ÿ5Ùª±¾¶jDà- ^yîÎy‘´ X)Ì‘T^!bGÀšn‰þÆpóçî¤ gWÞ­jO ]`µxHŒ  °´^O‡†C„†ƒÁ(HáSGõ3"ÐÆ0àm•ù6¦%CòíšÝszõhËÑ·U@ŸP‚ý"ÀE¤Â Qo·Â÷ðKîÐB¾¥ýUd”âÆ‘z4uâÆTÇhD`Œ$¨õÈû»Hf¡ªåŒ<üþE¿—”—ƒjÈËíU³ÔkBn5ÑWRœd X^!ìNmtDè &©Çc~n¼q\X¾º§OÈëóÛ>q÷'eÜ+zÈö#jÿ“ÿìý߯¢ÜW‡®(»î‘iê(xÊo‡u'xu¨¾‹ ±öìÁ|'s#9JÂaO¯`€ÔG‡~[ã€IO}#üÿwNŒL›eG´3ÖeþV0&¿)1Yme#K~ä`ˆ·Ÿ0H/s±¬4HGÐ Ù% )$FɈ%]–eb¿LÁ¬´)9÷²©8è¹QË2«@Q#¿±sW0ÿì /wxâ9<\"݉Z’‹‚ÃyÝ[;({.¤w÷ˆ’Ÿü‚ÀoGxLø0K2D—¨¥§šQB²ßÈâ¯F:y’;²¡K”ÿưa±ñ•|¡½¯k˜£+$¿©š* gØéJ‰*~š°‘bㆱú’LûsW˜,»ˆÆÅÖ²óK}bÿ•Ô”)ß³}&ƒw L„üvˆhÙ Ì9HÌ–J¢¼¥9MœLÈtß®p·|ªFuºÅØ€±²÷P¬,ýì6 *‡¸“OEä7[î3#kÅ6h: ÏhZ¥¸óá^@ìnÿqGœ­#œÝSʺ© Ó¡Qœ…-l0ËÑXÑ*ÃLN'ïÞ†C¿¥Ž„Ó²†ùÒ22³d¹ ü-j ¿ç²- lËnLÆ|KnÊ«O(ç0Å“\R<Ë¡Èó\*”§(vÉ’/Ž$%AŠFªiVùý.?¬ØÎ^Jí G§ ãTÑhÕ(#PÖaT\‹ˆ»•'ÝŸqByÔã_äKÌôçé´™è- .ªò-ã5ùÇyBœG¯Iˆ>çÍ“7㈱0lNäó#¨€Û[.4 !.zÓÍbÛÃëÖ¼¬M_ôùVTôYdE2»Œ¿MبÜùÆê”pF´¿¢•âóØ«ÓÅŠ)3£¢¬ãlª+½ïe½Û´‘%‹åHm9Ê–KÿÓw?Ñ ÅºÓ€T¥ÿËš]á= œ#éD£ _ׯJ®Qk¢.`¬ßÕÓæ5ÈQ:…ÄÒ²‡}d»2%{#îKiœÝyË îW‹ì¢¿VV²RFנɹP6¬¦¨5“z\ýó0û£³f«YÜE#+ÿN*œ5¹ÄªL«ÎÅ#uqbeÉ% ›­;mf¦¶DàšéþO¸Ð"ìÒÃë6ž¼™êÂ#Ê(!GP›rÑŸª˜<æ|½ñûAå+tcÑQÁm\Ðð&,à#ÏG)φl“†ÎWeà†3VÏ{]qýHœu„õJ•ÂS4笤ɛ"]âd†L˜×x@R›.®Hò@`›¹X }#æÔëÒÃroÓ¢Z>BJ+¦“< 8 +–òÊÓd™–cÑ^Þä™Túí;ÉSƒ *C7H•–HýÔ?_«Um‘Î^$ì~ )Ä5ŽŽbJ/lÏÔ.D5íüäh¾ Ô“@±R›°<;-]g²åôûˆ¹_ìѳÓç}×ÚúkÿÒk!ŽïI/^wÍöë;ñ„0 ˜äàhpƒ ÂG æþ|&ß³¥®=ÈýR.P(…ÀÖA¡ZFÛ²±é}ò yŸgo’^Íù:47“Í<ýÔWèS¦æUìuõG÷3qsýl%ËÌ:"“IL¥G‘¡tJ…‰Ÿ¥’'º¸Ò K4»µ ÍîêF³¼Ë‘£Ñù‡kÂi7NÛÚ €®ë@ÐÇ„cÀªä˜mSgûÅð(9š©Òû;®ÕÞÊöûHdv_¸àˆók*•ûLJô_¬ÞØoAJµBãœ[_„IM徨qøŒµ‚Ð?Ô˜¸úÖpþÎsÉ7ö|j£›l«†æ”L«$ÈQžsÈ©Ÿª«INßPo_®Ë%Ç+†ÝizYhañ^Mµ‰qa3Ú ¾uø§—åkaž‘Yo7¢ GR]æ\(¿I77e©UÓŽ nm±ÚOFÊ/™³ 'Ãô¼»µÊ‹.ò¤Œª)?*a|#-vþ®€]^ÑÝŒ½·ÉPlVäIƒß‘l¦ƒÎL”1³¼. g†ƒ\I>»r™s¥Ï¨03¢ãk*+3|¹"ž·ôb·1:{}3O¬ÜåAˆqzÇ‹gÒwÔ«4( ®°­rµŠQàV¢cyNkš¿;§µbñ°nœ…ºŠ}°²H¼DØÒâD¨€ Æ+±ð\Δ°½Û‡£ìî)S° súTíMÏ£¶’tF0BÃsüPÔïÿûÎ ége.ä.#Ày›=Ášén7i7ªÜ1u REçEÆ Í»®až ïB- éÀk y¹q…Þˆ°_h°µÝÄÐÝ‚îø'.Ð&Ÿ 3Žð6F` Çáá•Üi³·DŸ‡å¬Wµ‚*”$h6,ÿó$K†ÌwÈ™ý°³“JžšMùÒf%–"kª prM mú~áüòiRç«gÿ ÖS®e¸‹W&ï~àýŸFînüïââ7’‡5Î9~g§§ò…#ŒÙ7æôÛç8)XT¯k†³L¾‰Äíª‘:™_¤åÊÈâéJCéÿ»šØ¨ª(üJi‹`5&¨HÜ0ÛLÛé´¢i¤B%ŽBºp˜y…I;L÷*Œ˜`bÂF£ÀDbd!¨ F.LŒ–c"qEL\‰&ú6˜`â=?÷Þsß¼)%é‚sÏ»ÿ?ßwΙ{}¨/`;O KfH3&>À¹L›år9óþn\S®)–? ùI7Ü=µsçòˆmEvC{‰¸Êc\¦B]ð6]Uµ#×áîže‹;Æ Í˜).ù‹Š0·5>C;6••ÝDñ•î h_j»(¸ÆdgÔþáÐ¹Ž§¤þÀúDb¼mF,—Ø&p”!Uöœ ClÎ9Q«Ú@cç æ÷Y‘»¥Hà^ƒ0A“«Oc`™óÁ¢X¤Ó·ƒE$GÏéðÕb…ç˜j0Ï&-dãbZÈÕR¶±$[ß^èÚvåàRFô\TЍVühf‰û!Û;¼>¶÷×™5ÙÞD:‘íQ¼Uœ1¬/WÓ8@.W¯mA‰uá`vT_åb Ý¬~Ú”ö3htŒ#ßxP÷—¨v#ß²@b„)ª@Ø)rÄ.Ú«£ˆ3JZR€_PUª¼‘.%zŽ;¾pRÍç s~AÖ¢ Ž^fx+b©VÞ¥Ñ:0´‡Èj^×O8> _NxcÑo¶±"©u g7ÜÃ¿Êæ ô3¡N%MIì®v‡Ã„ãÒ% ?§Å’Œwé\]?B¥S¨#ù`väH9m^ ~â–BJ ™“±ý¤·ÈØéQÐîqá–·€4¦&¼cI´ @æaΪÝÎfÜOM¢L(3ZGÉqÆfFTÄeŠÇƒ‘…T ’î?ú%h`ÄÔ»º3ËÒJ@#JF2~½Möq6†|¶ôµNp¡8-<ã~˜¡kÈ“i'‚eý+\ˆ—üŒ40¤yÉåW¶Yg¢ Þ‹i}—âSº $u\ØàÕDÌ+¶sWCc*7¬Ú§1µ˜[tE²&^8d<{’ÆY»_]›Æ %Ò¸»Å¹éCßp¯î¡É4ëµÍDÆÀ(YZ›( âã¯53;X©-Ë=ˬg­Å¾|îî,ÏËq¹‡ö|œ µÀNBÙŠ°-Ìín-÷|TÑdUöK7~m?­å3Ó¦T_Òø÷Y|!J@®öKhZÇQæ«u?…çÿº‡Zƒ¸ÅQŠ]hÌ‘žç(Ò“)·V£Q†¨s|ÓܹçuoÎt}pᇧwÁé¾Ó£ëüSS^¿7ù ÜÛê=¢NôÍ*±¯T-¥¡tTþñ—Üeoë÷o{j¼ÞRõ詡ᨈʠè(ïCåm¿ís”÷îùùÏ¥í½îõ”ªõ¡±h7ªBqR5{ûìy”°4 •tu…uÓ‡®½±ÅH1Ûáè™Ûì>e*F¤£ÛÿI”R•A:J­\O¿.¥Á²’îøÏ{î%'‡Š’n¯}ûáMï!%¿ª°‰hÛΟÏy›Ôÿ7QÂÊxôÄ­®'‡¥°ª„¿wúÍ>#„¯Ç£G¿›,^õz¡ –e£þ©?wjÔPeoÞrùèËRZ…õíÿû­†‘bóÓQï¯ÍËs^Œ g:õœí¾tØë%–FÎü>û•?°GœTŸw9â^¥ÿõº^Ùp›þý7,›ó´pretzel-2.0n-2/doc/project.report/report-title.tex0000644000000000000000000000067006236070642020764 0ustar rootroot \title{ \vbox{ \begin{quote} \begin{flushleft} \Huge \leftskip20pt {\bf building a}\\ \qquad{language independent}\\ \qquad{\bf prettyprinter} \end{flushleft} \end{quote} } } \author{Felix G\"artner\thanks{This report covers the very first version of \pretzel{}. Consult the \pretzel{}book for the latest version of \pretzel{} documentation.}} \date{27. Februar 1995} \maketitle pretzel-2.0n-2/doc/project.report/slides.tex0000644000000000000000000003007710765024777017633 0ustar rootroot% slides.tex 20 Jul 95 %------------------------------------------------------------ % % These are the slides for the presentation on pretzel made on 21-7-95 % in Darmstadt. The code requires the seminar style for Latex (at least % the files sem-page.sty and seminar.sty). % % [LaTeX 2.09] \documentstyle[a4-9,german,portrait,pretzel,pretzel-latex]{seminar} \slidesmag{3} \begin{document} \slideframe{none} \def\sheader#1{ \begin{center}\Large\bf #1 \end{center}} % ------------------------------------------------------ \begin{slide*} \begin{center} \vbox{ \begin{quote} \begin{flushleft} \Large \leftskip20pt {\bf building a}\\ \qquad{language independent}\\ \qquad{\bf prettyprinter} \end{flushleft} \end{quote} } \bigskip {\small\sl Felix G"artner} \end{center} \bigskip "Uberblick: \begin{enumerate} \item Theorie: \begin{itemize} \item Was ist ein Prettyprinter? \item Wie funktioniert ein Prettyprinter? \item Wie funktioniert ein Pretzel-Prettyprinter? \end{itemize} \item Technik: \begin{itemize} \item Entwurf/Konzepte von Pretzel \item Blick ins Innere von Pretzel \end{itemize} \item Praxis: \begin{itemize} \item Der generierte Prettprinter \item Benutzung von Pretzel \item Beispiele\dots \end{itemize} \end{enumerate} \end{slide*} % ------------------------------------------------------ % Theorie 1: Prettyprinting \begin{slide*} \sheader{Theorie 1: Prettyprinting R"uckblick} \begin{quote} ``Rearrangement of source code to illuminate it's logical structure and thus enhance readability.'' \end{quote} Was macht Prettyprinting (genau)? \begin{itemize} \item Einr"uckung und Umbruch von Code-Zeilen \\ (globale Formatierung) \item lokale Formatierung (z.B.~von Ausdr"ucken) \item zus"atzliche typographische Raffinesse (Fonts, etc.) \end{itemize} % was ein prettyprinter ist, sollte am ANfang klar sein \medskip Wie arbeiten Prettyprinter? \begin{itemize} \item fr"uhe Systeme: reservierte Worte l"osen Formatierungsaktion aus \item moderne Systeme: Parsen des Codes und Abbildung von Teilb"aumen in Formatierung \end{itemize} \medskip Problem: Sprachabh"angigkeit \end{slide*} % ------------------------------------------------------ \begin{slide*} \sheader{Theorie 2: Prettyprinting heute} Hearn and Norman (1979): ``A one-pass prettyprinter'': \begin{itemize} \item sprachunabh"angiger Ansatz (``separation of concerns'') \item 2 ``Prozesse'', die sich die Arbeit teilen \end{itemize} \medskip \begin{description} \item[Parser] liest Sourcecode und f"ugt spezielle Markierungen ein. \item[Formatierer] bekommt Daten des Parsers und "ubernimmt das tats"achliche Layout \end{description} \begin{figure}[h] \begin{center} \leavevmode \input{../figures/pp-concept.latex} \end{center} \end{figure} Formatierungskommandos Unterschiedliche Befehlsvorr"ate \end{slide*} % ------------------------------------------------------ \begin{slide*} \sheader{Theorie 3: Prettyprinting -- Beispiel} \bigskip Pretzel benutzt Befehlsvorrat von Knuth/Levy aus \CWEAVE \medskip {\large\bf Beispiel: Steuerung der Einr"uckungstiefe} Input: \begin{inp} while (i #include "pparse.h" int main () { pparse(&cin,&cout); return(0); } \end{verbatim} \end{slide*} % ------------------------------------------------------ \begin{slide*} \sheader{Praxis 2: Benutzung von Pretzel} Bauen eines Prettyprinters ist einfach: \begin{itemize} \item Eingabedateien basteln \item pretzeln \item flex und Bison anwenden \item compilieren \item in minimales Hauptprogramm einbinden \end{itemize} Shellskript {\tt pretzel-it}: \begin{inp} pretzel-it $\langle${\it language}$\rangle$ $\langle${\it ppmain}$\rangle$ \end{inp} \bigskip Environment-Variablen: \begin{itemize} \item {\tt PRETZEL\_LIBDIR} \item {\tt PRETZEL\_INCLUDE} \end{itemize} \end{slide*} % ------------------------------------------------------ \begin{slide*} \sheader{Praxis 3: Beispiel} \bigskip \begin{verbatim} 2697 Jul 20 15:55 pascal.fg 2694 Jul 20 15:55 pascal.ft spock $ pretzel-it pascal pascalpp running pretzel... running flex and Bison... pascal.y contains 21 shift/reduce conflicts. compiling scanner... compiling parser... linking prettyprinter pascalpp... done. spock $ ll 2697 Jul 20 15:55 pascal.fg 2694 Jul 20 15:55 pascal.ft 45611 Jul 20 15:55 pascal.lex.c 32380 Jul 20 15:55 pascal.tab.c 253719 Jul 20 15:55 pascalpp 362 Jul 20 15:55 ptokdefs.h spock $ \end{verbatim} \end{slide*} % ------------------------------------------------------ \begin{slide*} \sheader{Praxis 4: Beispiel} \bigskip {\large Quellcode:} \begin{verbatim} program 'Hello'; begin writeln('Hello Pretzel!'); end. \end{verbatim} \medskip {\large Nach dem Parsen:} \begin{verbatim} \documenstyle[pretzel-latex]{article} \begin{document} \begin{ppcode} \pretzelbigforce\pretzelbackup{\bf program} {\tt 'Hello'};\pretzelforce {\bf begin} \pretzelindent\pretzelforce{\bf writeln} ({\tt 'Hello Pretzel!'});\pretzeloutdent \pretzelforce{\bf end}. \end{ppcode} \end{document} \end{verbatim} \medskip {\large \LaTeX-Output:} \begin{quote} \begin{ppcode} \pretzelbigforce\pretzelbackup{\bf program} {\tt 'Hello'};\pretzelforce {\bf begin}\pretzelindent\pretzelforce{\bf writeln}({\tt 'Hello Pretzel!'});\pretzeloutdent\pretzelforce{\bf end}. \end{ppcode} \end{quote} \end{slide*} % -------------------------------------------------- \begin{slide*} \begin{center} \vbox{ \begin{quote} \begin{flushleft} \Large \leftskip20pt {\bf building a}\\ \qquad{language independent}\\ \qquad{\bf prettyprinter} \end{flushleft} \end{quote} } \end{center} \bigskip {\Large Zusammenfassung:} \begin{itemize} \item Was ist Prettyprinting? \item Was sind Formatierungskommandos? \item Formatierte Grammatik \item 2 Eingaben $\rightarrow$ Pretzel $\rightarrow$ Prettyprinter \item Ausgabe in \LaTeX \end{itemize} \bigskip {\Large Anwendungen} \medskip {\Large Probleme} \medskip {\Large Ausblick} \end{slide*} \end{document} pretzel-2.0n-2/doc/project.report/index.list0000644000000000000000000000153106456666130017620 0ustar rootrootthis directory & Project Report of Pretzel V.1.1 (WARNING: OLD INFORMATION) Makefile & Makefile for documentation README & more details on the files herin report.dvi.gz & full version of the project report report.tex & main frame of the report report-title.tex & plain title (default) report-title2.tex & ITI title abstract.tex & the abstract report-intro.tex & introduction chap1.tex & chapter 1... chap2.tex & chap3.tex & chap4.tex & chap5.tex & acknowledge.tex & acknowledgements appendix.tex & intro to the appendix (full appendix not available automatically, see README) manual.tex & main frame of the user's manual (old) manual-title.tex & title of the manual manual-intro.tex & introduction to the user's manual erklaerung.tex & formal sheet for handing in itititle.sty & only used for report-title2 slides.tex & slides for the pretzel presentation pretzel-2.0n-2/doc/project.report/report.tex0000644000000000000000000000251606254322065017645 0ustar rootroot% % $Id: report.tex,v 1.3 1995/02/23 10:27:47 gaertner Exp $ % % This is the global frame of the report for the % pretzel project % % First Version designed from scratch on August 22, 1993. % % $Log: report.tex,v $ % Revision 1.3 1995/02/23 10:27:47 gaertner % Changes bibliography input to use bibtex output. % % Revision 1.2 1994/10/24 18:30:56 gaertner % Changed names of included files to current versions. % % Revision 1.1 1994/10/24 18:12:02 gaertner % Initial revision % % \documentstyle[pretzel]{report} \makeindex % creates an .idx file for MakeIndex \pagestyle{headings} \begin{document} % read the titlepage \begin{titlepage} \input{report-title} \end{titlepage} \begin{abstract} \input{abstract} \end{abstract} \tableofcontents \input{report-intro} % introduction \input{chap1} % chapters ... \input{chap2} \input{chap3} \input{chap4} \input{chap5} \input{acknowledge} % acknowledgements \input{appendix} \clearpage \addcontentsline{toc}{chapter}{Bibliography} \bibliographystyle{plain} \bibliography{../bibliographies/prettyprinting,../bibliographies/litprog,../bibliographies/supplemental} % % At last we reach the index. The index was generated with the % MakeIndex program. \addcontentsline{toc}{chapter}{Index} \printindex % reads the .ind file and prints the index % Here we have reached the end! \end{document} pretzel-2.0n-2/doc/project.report/README0000644000000000000000000000350306254322327016466 0ustar rootrootSome notes about the files in this directory: These files contain the main documentation of the pretzel project. This includes the main report, the user's manual (which is part of the main report, but can be printed out on its own too) W A R N I N G THIS DOCUMENTATION IS OLD AND ONLY COVERS PRETZEL UP TO VERSION 1.1! Files: ------ Makefile Makefile for documentation (see below) report.tex main frame of the report report-title.tex plain title (default) report-title2.tex ITI title abstract.tex the abstract report-intro.tex introduction chap1.tex chapter 1... chap2.tex chap3.tex chap4.tex chap5.tex acknowledge.tex acknowledgements appendix.tex intro to the appendix (see below ``full report'') manual.tex main frame of the user's manual manual-title.tex title of the manual manual-intro.tex introduction to the user's manual erklaerung.tex formal sheet for handing in itititle.sty only used for report-title2 slides.tex slides for the pretzel presentation Targets in the Makefile: ---------------------- report make the report (approx. 50 pages) manual make the user's manual fullreport make the full report including various specifications (approx. 90 pages) clean remove all intermediate files clobber remove dvi files too bundle bundle all together into a tar file Making a full report: --------------------- The full version of the report (as it was handed in) includes various specifications of the pretzel modules. To understand the program you will not need these specifications. However, if you want to make your own changes to the source, you need a version of them. But instead of printing them out within the report, I suggest that you go into the relevant subdirectories and print them out selectively. Normally there are Makefile rules to get a printout. pretzel-2.0n-2/doc/project.report/report-title2.tex0000644000000000000000000000115405745465312021052 0ustar rootroot% use the itititle style % try.tex 07 Feb 95 %------------------------------------------------------------ % % XXX % % [LaTeX2e] \documentclass[a4paper]{article} \usepackage{itititle} \renewcommand\TitleInstitute{Fachgebiet Systemprogrammierung} \begin{document} \title{ \vbox{ \begin{quote} \begin{flushleft} \Huge \leftskip20pt {\bf building a}\\ \qquad{language independent}\\ \qquad{\bf prettyprinter} \end{flushleft} \end{quote} } } \author{Felix G\"artner} \date{27. Februar 1995} \iti{Studienarbeit} \maketitle \end{document} pretzel-2.0n-2/doc/project.report/index.html0000644000000000000000000000426306456666137017625 0ustar rootroot Index file for directory "" of Pretzel distribution

Index file for directory "" of Pretzel distribution

Files and directories are:

this directory

    Project Report of Pretzel V.1.1 (WARNING: OLD INFORMATION)
Makefile
    Makefile for documentation
README
    more details on the files herin
report.dvi.gz
    full version of the project report
report.tex
    main frame of the report
report-title.tex
    plain title (default)
report-title2.tex
    ITI title
abstract.tex
    the abstract
report-intro.tex
    introduction
chap1.tex
    chapter 1...
chap2.tex
chap3.tex
chap4.tex
chap5.tex
acknowledge.tex
    acknowledgements
appendix.tex
    intro to the appendix (full appendix not available automatically, see README)
manual.tex
    main frame of the user's manual (old)
manual-title.tex
    title of the manual
manual-intro.tex
    introduction to the user's manual
erklaerung.tex
    formal sheet for handing in
itititle.sty
    only used for report-title2
slides.tex
    slides for the pretzel presentation

Felix Gaertner

To Pretzel Homepage.

Last modified: Tue Jan 13 14:30:09 MEZ 1998 pretzel-2.0n-2/doc/project.report/acknowledge.tex0000644000000000000000000000114006003444734020605 0ustar rootroot% % $Id: acknowledge.tex,v 1.2 1995/02/23 13:35:10 gaertner Exp gaertner $ % % $Log: acknowledge.tex,v $ % Revision 1.2 1995/02/23 13:35:10 gaertner % Final revision. % % Revision 1.1 1995/02/23 13:20:31 gaertner % Initial revision % % \chapter*{Acknowledgements} \addcontentsline{toc}{chapter}{Acknowledgements} I have to thank Joachim Schrod for his time and lasting inspiration on this subject. Also thanks to U.~Freiling for her continuous support during the time it took me to finish this project. \noindent\bigskip And of course thanks to Donald Knuth for the idea of literate programming. pretzel-2.0n-2/doc/project.report/chap3.tex0000644000000000000000000004430305745456750017345 0ustar rootroot% % $Id: chap3.tex,v 1.4 1995/04/20 13:13:03 gaertner Exp gaertner $ % % $Log: chap3.tex,v $ % Revision 1.4 1995/04/20 13:13:03 gaertner % Corrections proposed by JS % % Revision 1.3 1995/02/23 12:20:14 gaertner % Final revision (including index). % % Revision 1.2 1995/02/21 09:24:22 gaertner % Replaced \mkWEAVE with \pretzel. % % Revision 1.1 1995/02/21 09:21:47 gaertner % Initial revision % % \chapter{Literate Programming and \pretzel} \label{three} The \pretzel\ program is the result of a project that the author worked on in 1994 at the Technical University of Darmstadt. It is a small contribution to a larger project of research that has to do with the literate programming paradigm that I have already mentioned in the introduction to this report. This chapter now introduces the literate programming paradigm in slightly more detail and outlines the research project of which \pretzel\ is only a small part. Taking this larger frame into account, I will finally describe the role that \pretzel\ could play in this research. \section{On Literate Programming} ``When was the last time you spent a pleasant evening in a comfortable chair, reading a good program?'' asks Jon Bentley in the introduction to his regular column in the Communications of the ACM \cite{Bentley:CACM-29-5-364}. As might be suspected, Jon Bentley is far from being sarcastical; his question is meant seriously and our not taking him seriously reveals only the poor attitude we have towards the readability of a program's source code. \index{Bentley, Jon}\index{ACM}\index{Sarcasm} But how can it be pleasant and amusing to read a program, if this program is simply another sequence of programming language commands destined for a compiler, that---if we are lucky---may be decorated with a few lines of commentary? This surely isn't very pleasant; but the reading and understanding of a program is far too important to be unpleasant. The only way to get out of this dilemma is to write programs with a different attitude: Programs are not merely lines of code that primarily instruct a computer to act in a special way; programs must be destined to meet the eye of a {\em human being} and explain him or her what the author wants a computer to do \cite[p.~97]{Knuth:CJ-27-2-97}. Though this necessity has long been recognized, it is due to Donald Knuth and his idea of ``literate programming'' that today programs can be written in a style that makes comprehension of source code indeed a pleasant and rewarding job. The name of his new concept is derived from the idea, that programs should be considered {\em works of literature\/}; in the course of this idea, the programmer's main concerns switch from efficiency and brevity to exposition and excellence of style (without forgetting the first two goals of course). Considering this turning of approach, Knuth's idea can legitimately be called a new {\em programming paradigm} \cite{Cordes:COMPUTER-24-6-52}. \index{Knuth, Donald E.}\index{works of literature@``works of literature''} \index{Programming paradigm}\index{Exposition and excellence of style} \index{Literate programming} There has been (and still is) a lot of discussion concerning the question of what makes a program literate or what languages really support a literate programming style. However, there seems to be a consensus that literate programming languages must enable the programmer to be absolutely free in choosing the order and way of presenting his ideas. It must be possible to use a top-down approach of presentation as well as a bottom-up approach or even a mixture of both. The key notion here is that it must support arbitrary {\em refinements} together with an easy way to insert comments into the program (imagine the notion of delimiting parts of the source code instead of bracketing comments, as you would normally do in traditional languages). The only restriction the programmer should have to worry about is the limitation of his own programming skills. \index{Refinements} In 1984 Knuth presented a first literate programming language that was based on \PASCAL, which he called \WEB. In fact, he didn't introduce a whole new language: \WEB\ programs and \PASCAL\ programs are essentialy the same thing, only that the \PASCAL\ source code is split into small pieces and shuffeled around in a \WEB\ program. Knuth proved that his \WEB\ system was practicable by writing (among other smaller examples) a full scale software system in it, namely \TeX~\cite{Knuth:ct-b,TeXbook}. These two things, together with his naming of the area, are Knuth's main contributions to the idea of literate programming. \index{web@\WEB}\index{pascal@\PASCAL}\index{tex@\TeX} \subsection{The \WEB\ system} A conventional \WEB\ system---like that first presented by Knuth \cite{Knuth:CJ-27-2-97}---is chiefly a combination of two other languages: % \begin{itemize} \item a document formatting language and \item a programming language. \end{itemize} % Knuth's initial \WEB\ used \TeX\ as document formatting language and \PASCAL\ as programming language, but the idea is chiefly independent of the underlying languages. A literate program is a combination of these two languages: commentary is written in the document formatting language, source code is written in the programming language. The \WEB\ system itself only provides a small set of commands that allow the user to switch between these two languages and that identify the actual order of the source code making it possible for a normal compiler to handle it. As implied by the last sentence, one main part of the \WEB\ system is a routine that converts a literate program into a form, that a conventional compiler may understand; the converted code then may be compiled into a machine-executable program. This way of processing is called {\em tangling the web} and the corresponding system routine is called \TANGLE. The second main line of processing converts the \WEB\ into a high quality document that serves as a source code documentation. This line is called {\em weaving the web}, the system routine perfoming this task consequently \WEAVE. These two lines of processing are visualized in figure \ref{web-system}. \begin{figure} % put picture here \begin{center} \unitlength1cm \begin{picture}(12,7) \put(4.5,5.5){\framebox(2,1){{\tt .WEB}}} \put(2,3.5){\framebox(1.5,1){{\tt .PAS}}} \put(2,1){\framebox(1.5,1){{\tt .EXE}}} \put(7.5,3.5){\framebox(1.5,1){{\tt .TEX}}} \put(7.5,1){\framebox(1.5,1){{\tt .DVI}}} \put(4.5,5.5){\vector(-3,-2){1.5}} \put(2.5,5.2){\TANGLE} \put(3,3.5){\vector(0,-1){1.5}} \put(1,2.7){\parbox{19mm}{PASCAL-Compiler}} \put(6.5,5.5){\vector(3,-2){1.5}} \put(7.5,5.2){\WEAVE} \put(8,3.5){\vector(0,-1){1.5}} \put(8.5,2.7){\parbox{3cm}{\TeX}} \put(1,0.4){\large Program} \put(8,0.4){\large Document} \end{picture} \end{center} \caption{\label{web-system}The two lines of processing in Knuth's initial \WEB\ system.} \end{figure} As stated above, the idea of \WEB\ is basically language independent. The past few years have seen many new \WEB\ systems for a lot of different combinations of languages. Many of them have been inspired copies of Knuth's initial \PASCAL-\WEB, like for example \CWEB\ \cite{Knuth:CSS93} for \C, \CPP\ and \TeX. As mentioned earlier there has also been a lot of disagreement on what exactly a \WEB\ system must be able to do. This is mostly due to the language dependency of the weaving process. Today one can see three main categories of \WEB\ systems: \begin{enumerate} \item In this category you would find Knuth's initial \WEB\ system. The structure of the underlying languages are hard-wired into the implementation and the output (mostly in \TeX) is of high quality and sees the program code beautifully prettyprinted. Moreover an index of identifiers is generated as well as a complex cross-reference of sections. \index{Prettyprinting} \item Here, the language dependencies are excluded from the actual \TANGLE\ and \WEAVE\ processors and put into modules. When writing a literate program the user can switch between programming languages and formatting languages by choosing the appropriate modules. An example for such a \WEB\ system is \t{FWEB} by John Krommes \cite{Krommes:fortran-web}. \index{Krommes, John}\index{fweb@\t{FWEB}} \item This category collects all the \WEB\ systems that are more or less programming language independent (\LaTeX\ is mostly used as document formatting language). Due to this independency, these \WEB\ systems have no prettyprinting feature and are not able to generate indexes or cross references. Examples for these kinds of \WEB{}s are \t{funnelweb} \cite{Williams:FUM92}, \t{noweb} \cite{Ramsey:LPT92} and \t{nuweb} \cite{Briggs:NUWEB-93}. \index{latex@\LaTeX}\index{Funnelweb}\index{Noweb}\index{Nuweb} \end{enumerate} There is also a generator for \WEB\ systems called \t{SpiderWEB} written by Norman Ramsey \cite{Ramsey:CACM-32-9-1051} that produces a category~one-\WEB. The \pretzel\ program was inspired very much by this approach (and this report also owes its title to Ramsey's paper). However, \pretzel\ does not produce a whole functional \WEAVE\ program, but generates only a prettyprinter. But because the prettyprinting is the most intricate part of the systems of categories one and two, it would not be a major problem to construct a \WEB\ system around it. But as \pretzel\ produces a ``prettyprinting block'' for a specific programming language, the resulting \WEB\ system would rather belong to category two. \index{Spiderweb}\index{Ramsey, Norman} The name ``\WEB'' has different origins. Knuth writes: ``I chose the name \WEB\ partly because it was one of the few three-letter words of English that hadn't already been applied to computers.'' \cite{Knuth:CJ-27-2-97} Another source Knuth refers to is the name of the mother of Knuth's wife, Wilda Ernestine Bates \cite[p.~2]{Knuth:web83}. Seriously, the name of the system and its subcomponents \TANGLE\ and \WEAVE\ is a reminiscence to the popular english proverb: % \index{Bates, Wilda Ernestine}\index{Knuth, Donald E.}\index{web@\WEB!name of} % \begin{quote} Oh, what tangled web we weave When first we practice to decieve. \end{quote} \subsection{The Literate Programming Paradigm and the Software Life Cycle} The \WEB\ system was originally designed ``for system programmers, not for high school students or for hobbyists''~\cite[p.~111]{Knuth:CJ-27-2-97}. This implies that the literate programming paradigm concentrates on the development and the documentation of actual system code~\cite[p.~55]{Cordes:COMPUTER-24-6-52}. So when reviewing the software life cycle is becomes apparent, that literate programming covers only parts of it, namely the implementation and additionaly the final stage of maintenance (see figure \ref{life-cycle}). \index{Life cycle}\index{Software life cycle} \begin{figure} % put picture here \begin{center} \setlength{\unitlength}{0.012500in}% % \ifx \SetFigFont\undefined \begingroup\makeatletter % extract first six characters in \fmtname \def\x#1#2#3#4#5#6#7\relax{\def\x{#1#2#3#4#5#6}}% \expandafter\x\fmtname xxxxxx\relax \def\y{splain}% \ifx\x\y % LaTeX or SliTeX? \gdef\SetFigFont#1#2#3{% \ifnum #1<17\tiny\else \ifnum #1<20\small\else \ifnum #1<24\normalsize\else \ifnum #1<29\large\else \ifnum #1<34\Large\else \ifnum #1<41\LARGE\else \huge\fi\fi\fi\fi\fi\fi \csname #3\endcsname}% \else \gdef\SetFigFont#1#2#3{\begingroup \count@#1\relax \ifnum 25<\count@\count@25\fi \def\x{\endgroup\@setsize\SetFigFont{#2pt}}% \expandafter\x \csname \romannumeral\the\count@ pt\expandafter\endcsname \csname @\romannumeral\the\count@ pt\endcsname \csname #3\endcsname}% \fi \endgroup \fi \begin{picture}(330,75)(30,690) \thinlines \put( 99,765){\line( 0,-1){ 45}} \put(141,765){\line( 0,-1){ 45}} \put(225,765){\line( 0,-1){ 45}} \put(273,765){\line( 0,-1){ 45}} \put(141,690){\line( 0, 1){ 6}} \put(141,696){\line( 1, 0){ 81}} \put(222,696){\line( 0,-1){ 6}} \put( 30,720){\framebox(330,45){}} \put(276,690){\line( 0, 1){ 6}} \put(276,696){\line( 1, 0){ 84}} \put(360,696){\line( 0,-1){ 6}} \put(297,702){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}? ? ?}}} \put( 37,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Specification}}} \put(280,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Maintenance}}} \put(233,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Testing}}} \put(148,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Implementation}}} \put(104,735){\makebox(0,0)[lb]{\smash{\SetFigFont{10}{12.0}{rm}Design}}} \end{picture} \end{center} \caption{ \label{life-cycle} Life-cycle coverage offered by the literate paradigm% %\cite[p.~57]{Cordes91} . } \end{figure} Current examples of literate programs however feign that writing a literate program from scratch is a valid programming method; they do not properly emphasize the importance of formalized system specification and design. However the descriptive features that are inherent to the paradigm provide a strong bridge between specification, design and implementation. Thus it seems possible to integrate the literate paradigm much further into the software life cycle. This issue is a field of further research at the TH Darmstadt. \index{Darmstadt} \section{``Literate Software Management''} Software systems today run during their evolution through what is called a {\em software life cycle}. One iteration of this life cycle begins with the global aspects of the specification, goes through the system design and the implementation, runs through the testing phase and ends with the maintenace of the software system. As todays software continuously has to react to market or other changes, it is usual that such systems run through the software life cycle more than once. Every phase of the life cycle has it's own tools; most apparent are programming languages if you think of the implementation phase. However there also exist tools that help pipeline software systems through their life cycle, help to keep track of revisions, describe the overall structure of the system and so on. The comination of such tools is normally called a {\em software management system.} \index{Software management systems} As mentioned in the end of the previous section, the literate programming paradigm applies only to small parts of the software life cycle, namely those that are covered by the term {\em programming in the small\/}. However the literate paradigm also offers a lot of features that also seem usefull to the other parts of the software life cycle. The main features are as follows: % \begin{itemize} \item Formal and informal description methods are combined leading to more readable text (the method of ``saying everything twice''). \item Through the recording of subsequent changes during a phase and the description of alternatives in the informal text, design decisions become more transparent and understandable. \item Additionally, information retrieval methods like index and cross reference may be a model for similar things on a larger scale. \end{itemize} Research is taking place at the TH Darmstadt to apply the benefits of literate programming to the whole software life cycle. This research runs under the title ``Software als Buch. Methoden und Werkzeuge f\"ur das literarische Softwaremanagement'' \cite{Detig92} (what may be translated as ``Software as a Book. Methods and tools for literate software management''). A software management system is under development that incorporates ``literate'' features and shifts the whole management process to become literature itself; the software system becomes a software book, or better: a SoftBook. The underlying model is based upon division of a so called {\em depot} and a {\em workspace}. The workspace supplies an environment of working on the software system no matter in what stage of the life cycle it should be. The depot provides a general (non-standard) database that stores documents and system parts from all phases of the life cycle. These parts can therefore vary a lot: whilst system parts from the design phase may be written in a formal and abstract design language, other parts can be simple essays and others may consist of hard-core assembly code. All these parts are connected with each other as a hypertext. \section{The Role of Pretzel} In the so called workspace, the user may work on the software system in various ways: he might change the design, implement modules or just examine documents that belong to previous versions of the system. In all these cases the information that is stored in the depot has to be visualized on the screen. Thinking of the software system as a book, the output for the user hast to be of high quality and formal code should be formatted to local standards. Considering the large amount of possible languages that you may encounter in software development, you may not use a universal module for formatting. This is where the \pretzel\ program plays its role. As shown above, it is possible to generate prettyprinting functions with \pretzel\ for a large variety of languages in fairly short time. These prettyprinting functions then may be turned into modules of the software management system that take over some of the ``weaving'' that is required to visualize the contents of the depot. Anyway, with \pretzel\ it could be possible to build one's personal \WEAVE\ system rather easily, because the prettyprinting is the most intricate part of the weaving process. The only major thing left is to generate an index and the cross reference and to build the major frame. A simple approach would be to change the one existing \WEB\ generator, namely the \t{SpiderWEB} system, and change it to use a \pretzel\ generated prettyprinter. Another possible way would be to build a prettyprinting back end for \t{noweb} that is language independent and uses the \UNIX\ toolbox paradigm. Prettyprinting will surely remain a major aspect of literate programming even though a lot of people do not believe in its worth. But, as Marc van Leeuwen puts it, it is a question of personal taste: \index{leeuwen@Leeuwen, Marc van} \begin{quote} ``Nevertheless I strongly disagree with people saying that pretty-printing is not worth the effort for anyone in general; this depends very much on ones particular situation and purpose. In some cases pretty-printing may even be the main reason to opt for literate programming.'' \cite{vanLeeuwen95} \end{quote} pretzel-2.0n-2/doc/project.report/appendix.tex0000644000000000000000000000201305745460032020133 0ustar rootroot% % $Id: appendix.tex,v 1.2 1995/04/20 13:22:25 gaertner Exp gaertner $ % % $Log: appendix.tex,v $ % Revision 1.2 1995/04/20 13:22:25 gaertner % Note the pagenumbering. % % Revision 1.1 1995/02/23 13:34:44 gaertner % Initial revision % % \chapter*{Appendix} \addcontentsline{toc}{chapter}{Appendix} \section*{Specifications} Included in this report are the specifications of the following modules: \begin{itemize} \item The \id{Attribute} class and the \id{Output} class from the run-time library. \item The scanners for the formatted token and formatted grammar files. \item The generator functions \id{build\_pscan} and \id{build\_pparse} for the prettyprinting scanner and parser. \item The generated prettyprinting scanner (default header file). \item The generated prettyprinting parser (default header file). \end{itemize} \noindent Unfortunately I was unable to provide correct page numbers to these parts of the report. However, the bibliography and the index at the end are numbered correctly again. pretzel-2.0n-2/doc/project.report/Makefile0000644000000000000000000000477406254321540017255 0ustar rootroot# # $Id: Makefile,v 1.2 1995/02/21 09:03:58 gaertner Exp gaertner $ # # Makefile for the pretzel projcet documentation # # $Log: Makefile,v $ # Revision 1.2 1995/02/21 09:03:58 gaertner # Installed dependency between input and output files in the # rules that produce report and manual in order to be able to # just type `make' if I have changed anything. # # Revision 1.1 1994/10/24 18:38:14 gaertner # Initial revision # # # where to copy any latex styles to: TEXINPUTSDIR = /users/gaertner/tex/inputs # name of the main documentation frame (without .tex): REPORT = report # name of the user manual frame (without .tex): MANUAL = manual # which dvi file should be made by default? DOCUMENT = report.dvi # text files that belong only to the report: REPFILES= report-title.tex abstract.tex report-intro.tex \ chap1.tex chap2.tex chap3.tex chap4.tex \ chap5.tex acknowledge.tex appendix.tex \ report.tex report-title2.tex # text files that belong only to the manual: MANFILES= manual-title.tex manual-intro.tex # text files that belong to both: BOTHFILES= chap2.tex \ ../bibliographies/prettyprinting.bib \ ../bibliographies/litprog.bib \ ../bibliographies/supplemental.bib \ ../figures/pretzel-in-concept.latex \ ../figures/pretzel-in-concept.fig \ ../figures/pp-concept.latex \ ../figures/pp-concept.fig \ ../figures/module-depends.latex \ ../figures/module-depends.fig \ ../figures/generator-funs.latex \ ../figures/generator-funs.fig \ ../figures/detailed-concept.latex \ ../figures/detailed-concept.fig \ ../figures/concept.fig # other files for the distribution: #DISTFILES= # name of the distribution: #DISTNAME = pretzel-doc # ----------------------------------------------------------------- doc: $(DOCUMENT) $(REPORT): $(REPORT).dvi $(REPORT).dvi: $(REPFILES) $(BOTHFILES) latex $(REPORT).tex makeindex $(REPORT) bibtex $(REPORT) latex $(REPORT).tex latex $(REPORT).tex fullreport: $(REPORT) itititle echo Sorry for this, but you will have to do some work here: echo Look at the README file. itititle: latex2e report-title2.tex $(MANUAL): $(MANUAL).dvi $(MANUAL).dvi: $(MANFILES) $(BOTHFILES) latex $(MANUAL).tex makeindex $(MANUAL) latex $(MANUAL).tex # packedreport - make a dvi.gz of the entire report packedreport: $(REPORT) gzip $(REPORT).dvi clean: rm -f *.toc *.log *.aux *.idx *.ilg *.bbl *.blg *.ind clobber: clean rm -f *.dvi bundle: tar cf $(DISTNAME).tar $(REPFILES) $(MANFILES) $(BOTHFILES) \ $(DISTFILES) release: pretzel-2.0n-2/doc/project.report/abstract.tex0000644000000000000000000000207705745446372020153 0ustar rootroot% % $Id: abstract.tex,v 1.3 1995/04/20 12:00:45 gaertner Exp gaertner $ % This report is the main documentation to a project that the author worked on at the Technical University of Darmstadt in 1994. The goal of the project was to build a prettyprinter generator, i.e.~a program that created a prettyprinter from a formal description of the way it should prettyprint given source code. The result was called ``the \pretzel\ system''. This text first gives an overview over the area of prettyprinting and presents the prettyprinting method used by the generated prettyprinter. It then describes how to use the \pretzel\ program to build a prettyprinter program or module of your choice. The remaining chapters deal with the literate programming paradigm, from which this program emerged, and an overview over the design of the system. % % $Log: abstract.tex,v $ % Revision 1.3 1995/04/20 12:00:45 gaertner % program = program or module % % Revision 1.2 1995/02/21 09:16:20 gaertner % Small fine tuning. % % Revision 1.1 1994/10/24 19:18:02 gaertner % Initial revision % % pretzel-2.0n-2/doc/project.report/chap2.tex0000644000000000000000000011054510765024757017342 0ustar rootroot% % $Id: chap2.tex,v 1.8 1995/04/20 13:08:27 gaertner Exp gaertner $ % % $Log: chap2.tex,v $ % Revision 1.8 1995/04/20 13:08:27 gaertner % Corrections proposed by JS % % Revision 1.7 1995/02/24 09:26:10 gaertner % Final touches. % % Revision 1.6 1995/02/23 12:19:37 gaertner % Deleted noisy index entries. % % Revision 1.5 1995/02/23 10:59:47 gaertner % Fine tuned whole chapter (including index). % % Revision 1.4 1994/10/31 18:33:54 gaertner % Finished revision of this chapter. Need to do some fine % tuning later. % % Revision 1.3 1994/10/27 18:33:21 gaertner % Revised text up to section about the `preBISON' file. Added % a section about advaced topics that still has to be filled. % Contents will be the redefinition of scanner and parser % interfaces and inclusion of additional C code at the end. % % Revision 1.2 1994/10/25 16:48:42 gaertner % Went over beginning sections of this chapter. Revised % first figure. % % \chapter{\label{two}Using Pretzel} Pretzel is a program that generates a prettyprinter module from a formal description of the way a certain language should be prettyprinted. (NB: Pretzel produces {\em modules}, not programs!) This chapter is the user's manual for \pretzel. It first gives an overview of how \pretzel\ works and how the generated prettyprinter can be used. Secondly it takes a close look at the formats of the two input files to \pretzel, the formatted token and the formatted grammar files. Thirdly, this chapter states how the program is invoked and how the input is turned into the prettyprinter. Finally there is a complete example for a prettyprinter for \PASCAL\ that was generated by \pretzel. \index{User's manual}\index{pascal@\PASCAL} \section{The Concept of Pretzel} The concept of \pretzel\ is visualized in figure \ref{concept}. From a formal formatting description of a programming language $P$, \pretzel\ generates a prettyprinting function that can be used to prettyprint source code in $P$. To get the actual prettyprinting program, you only have to supply a main program (or use the one that comes with \pretzel). If the way of prettyprinting needs to be changed, the user only needs to change formal parts in the input and use \pretzel\ again to get an enhanced prettyprinter. \index{pretzel@\pretzel!concept} \index{P@$P$} \begin{figure} \begin{center} \setlength{\unitlength}{0.012500in}% \begin{picture}(203,87)(8,744) \put( 90,789){\makebox(0,0)[b]{pretzel}} \thinlines \put( 54,744){\framebox(72,18){}} \put( 87,777){\vector( 0,-1){ 9}} \thicklines \put( 30,753){\vector( 1, 0){ 18}} \put(129,753){\vector( 1, 0){ 24}} \thinlines \put( 66,783){\framebox(45,18){}} \put( 87,819){\vector( 0,-1){ 12}} \put( 90,822){\makebox(0,0)[b]{formal description}} \put( 90,750){\makebox(0,0)[b]{prettyprinter}} \put( 18,750){\makebox(0,0)[b]{Text}} \put(183,759){\makebox(0,0)[b]{prettyprinted}} \put(177,744){\makebox(0,0)[b]{text}} \end{picture} \end{center} \caption{The concept of \pretzel.} \label{concept} \end{figure} Figure \ref{detailed-concept} on page \pageref{detailed-concept} shows the generating process in slightly more detail. The figure shows that the program \pretzel\ doesn't generate a prettyprinter immediately; what it does is to produce code that can be turned into a \CPP\ prettyprinting function with the help of two tools: % \index{c++@\CPP} % \begin{description} \item[flex] A POSIX.2 compliant lexical analyser generator. \item[Bison] A POSIX.2 compliant parser generator. The version used with \pretzel\ has to produce \CPP\ compliant source. \end{description} \index{flex}\index{Bison}\index{POSIX} \noindent Users that are already familiar with the basics of both tools will find it easier to read the following text because the way of specifying input to \pretzel\ is quite close to the ways used by them. However, this text aims at people who don't have such knowledge and will explain everything that is necessary. Also visible from this figure is that \pretzel\ creates two things: \begin{itemize} \item A prettyprinting scanner and \item a prettyprinting parser (the actual prettyprinter). \end{itemize} \index{Prettprinting scanner}\index{Prettyprinting parser} The prettyprinting parser is the actual prettyprinter function that you normally want to get when using \pretzel. The prettyprinting scanner is used by the parser and takes care of the token formatting. Both parts are separate modules with a well defined interface and can be used individually. Hence, you can write your own scanner or parser if you really need features that the ones produced by \pretzel\ don't have. (For a description of the interface to both, see section \ref{pp-interface} or the specifications of the two generator functions for a complete reference.) \subsection{The Input Files} The word ``pretty'' is very subjective and so programming language source code can be printed in a ``pretty'' kind of fashion in almost infinitely many ways, according to the taste and preferences of the user. If the task of prettyprinting is handed over to the computer, the user must specify in detail all of his wishes towards the appearance of the output of the prettyprinter. To generate a prettyprinter, \pretzel\ needs two descriptions that it expects to find in two different files: \begin{description} \item[A formatted token file.] This file should contain all information concerning the individual formatting of tokens (i.e.~identifiers, reserved words, etc.). \item[A formatted grammar file.] This file should contain a prettyprinting grammar, i.e.~a context free grammar enhanced with formatting commands. This information is necessary to handle the more global aspects of prettyprinting that need information about the language context (i.e.~indentation, line breaks, etc.). \end{description} \index{Formatted token file}\index{Formatted grammar file} \noindent The name of the first file might be a little misleading, since it doesn't contain formatted tokens. Instead it tells you what you will get from the definitions therein. A name like ``token formatting file'' might have been a little better, but the similarity in names between the two input files sounded good and seemed to outplay this small inconsistency. The special formats of these two files are described later in section \ref{file-formats}. Let's first look at what the generated scanner and parser functions look like. \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/detailed-concept.latex} \end{center} \caption{The current process of generating a prettyprinter with \pretzel.} \label{detailed-concept} \end{figure} \subsection{The Generated Prettyprinting Functions} \label{pp-interface} So there are two inputs to \pretzel. And if these inputs are okay and the program runs without error, you will obtain an output from which a \CPP\ prettyprinting function can be made. The output of \pretzel\ are two files. The first file is a valid Bison file from which the actual prettyprinting parser can be obtained. The second file (generated from the formatted token file) can be processed with the scanner generator to form the prettyprinting scanner used by the parser. \index{Bison}\index{c++@\CPP} The generated Bison file contains all definitions for the actual prettyprinting function. It's default interface is: \begin{outp} \res{void} \id{pparse} (\id{istream}$\ast$, \id{ostream}$\ast$); \end{outp} This is in the flesh the desired prettyprinter. The input (source code text) enters the prettyprinter through an input stream (i.e.~a \CPP\ \id{istream} object) and leaves the prettyprinter through an output stream (i.e.~a \CPP\ \id{ostream} object). This output isn't actually prettyprinted yet. By default the output is delivered in a format suitable for \TeX\ to typeset it. It can be changed however to suit any other typesetter. (The output format is very much part of the implementation of the \id{Output} class. See into the appendix for details.) The prettyprinting function depends on a separate function that cuts the input file into small bits (tokens) and does the local formatting. This function is provided in the scanner generator source produced from the formatted token file. It's default interface consists of two functions: \begin{outp} \res{void} \id{pscan\_init} (\id{istream}$\ast$);\myforce \res{int} \id{pscan} (\id{Attribute}$\ast\ast$); \end{outp} The first function serves as an initializer and tells the scanner where it should take its input from. The second function is the actual scanner. It scans the input and returns token codes as integer numbers. These codes have to be the same as the ones used by the parser (look at section \ref{fg-file} for details). The formatted look of this token is handed back as a call-by-reference argument of type \id{Attribute}. \index{attribute class@\id{Attribute} class} \index{Interface of the scanner} Please note that the interface of the prettyprinting scanner is exactly how the parser above expects it to be. If you are planning to create a normal prettyprinter you won't have to bother about the interface of the scanner, because it works together fine with the parser. If you really need to know more details or want to change the default interface in any way, look into section \ref{hacks} for a description of some of the more specialized topics. To use the prettyprinting functions in a \CPP\ program, header files are needed that declare the interface. From the information above it is possible for you to write your own header files for the generated scanner or parser. But \pretzel\ spares you from this job, however, as it offers two template header files that you can copy and edit to suit your own purposes. They provide the default interface of both functions. Look into the {\tt README} file for an exact description of their location in the \pretzel\ distribution. \section{The Format of the Input Files} \label{file-formats} \index{File formats} Now we turn to a vital thing for the user of \pretzel: The format of the \pretzel\ input files. Here the user has to put a formal description of the underlying programming language and (with the help of format commands) state how its text should be formatted. We have seen that \pretzel\ takes two input files: The formatted token file and the formatted grammar file. We suggest to use the suffix `{\tt .ft}' for a formatted token file and `{\tt .fg}' for a formatted grammar file. \index{ft@\t{.ft} suffix}\index{fg@\t{.fg} suffix} \index{Filename conventions}\index{Conventions} \subsection{The Formatted Token File} \index{Formatted token file} The formatted token file contains a list of token definitions with their corresponding ``prettyprinted'' form. The prettyprinted form of a token will be called an {\em attribute} or a {\em translation}. The general outline of the formatted token file is % \begin{outp} \id{declarations} \t{\%\%} \id{token definitions} \end{outp} % Normally, the {\em declarations} part is empty. You can put a general description of the file here (as a \C\ comment) and redefinitions of the default interface go here as well (see section \ref{hacks} for more). The {\em token definitions} section of the formatted token file contains a series of token definitions of the form: % \begin{outp} \id{pattern}\qquad \id{token}\qquad \{\id{attribute}\} \end{outp} % The {\em pattern} must be a valid regular expression (in terms of {\tt flex}) and must be unindented. The {\em token} specifies the symbolic name of the token for the pattern and begins at the first non-whitespace character after the pattern. The token name must be a legal name for an identifier in \PASCAL\ notation and {\em must be all in upper case}. (Underlines are allowed but not at the beginning of a word.) \index{pascal@\PASCAL} The {\em attribute} for this token, that is it's prettyprinted form, consists of all text between the two curling brackets `\{' and `\}'. Attributes can be either simple strings (surrounded by double quotes) or format commands (like \fmt{force}, \fmt{indent}) or a combination of both joined together by the `\t{+}' sign. Attribute definitions can cover several lines and the starting `\{' needn't stand on the same line as the token definition; however subsequent lines must be indented with at least one blank or one tab. If you define strings as part of an attribute definition, you have to specify them in a \C\ kind of fashion, i.e.~you can insert newlines and tabs with `\verb+\n+' and `\verb+\t+'. But if you want to insert a backslash into a string, you mustn't forget to put two backslashes (`\verb+\\+') into the input file. This is especially noteworthy if you are using \TeX\ as typesetter, because \TeX\ uses a backslash as a prefix for typesetting commands. If the definition of the attribute is omitted \pretzel\ creates an attribute for this pattern by default. The default attribute consists of the string containing the text matched by the corresponding pattern. The user himself may also refer to the matched text by using the sequence `\t{**}'. Thus % \begin{verbatim} "foo" BAR "foo" BAR { ** } "foo" BAR { "foo" } \end{verbatim} % all have the same meaning. You can use a `\t{|}' sign as a token name; this signals that the current regular expression has the same token name (and also the same attribute) as the token specified in the following line (empty lines are ignored). An attribute definition behind a `\t{|}' is illegal. However you may specify regular expressions with neither a token name nor an attribute to give a default rule or to eat up whitespace. The following examples are all legal token definitions (and please note the dot in the very last line): \begin{verbatim} [0-9] DIGIT "{" OPEN { "\\{" + indent + force } [a-z][a-z0-9]* ID { "{\\it " + ** + "}" } "function" | "procedure" PROC_INTRO { big_force + ** } [\t\ \n] | . \end{verbatim} The declarations and the token definitions must be separated by a line containing only the two characters \t{\%\%}. So the shortest possible formatted token file is % \begin{verbatim} %% \end{verbatim} % but this doesn't seem of any use, does it? \subsection{The Formatted Grammar File} \label{fg-file} \index{Formatted grammar file} In the formatted grammar file the user encodes the general prettyprinting grammar for the programming language. This is done by specifying a context free grammar of the language and by adding information about the creation of new attributes in every rule. \index{Context free grammar} The formatted grammar file is the second and last input to the \pretzel\ program. Its general outline looks like this: \begin{outp} \id{token declarations} \t{\%\%} \id{grammar rules} \end{outp} The {\em token declarations} section may be empty and the separator between the two parts of the file (\t{\%\%}) must appear unindented on a single line by itself. Before we look at these declarations, let's have a look at the grammar rules. The {\em grammar rules} section contains the collection of rules of the context free grammar that can be accompanied by an attribute definition. A rule is specified by stating the resulting token, a colon and then the series of tokens which will be reduced by this rule. The rule is ended by a semicolon. A block definition in \PASCAL\ for example might look like this: % \begin{verbatim} block : BEGIN stmt_list END ; \end{verbatim} Following the token list on the right side of the colon can be an attribute definition; this definition states, how the translation of the produced symbol is obtained from the tokens on the right side of the rule. An attribute definition is bracketed amidst curling brackets `\{' and `\}' and can again consist of strings (in double quotes) and format commands or both joined together with `\t{+}'. But here you can also refer to the attributes of the tokens on the right side of the rule. This is done in a slightly awkward notation with a number that is preceded with a `\t{\$}' dollar sign. The numbers refer to the order of appearance of the symbols on the right side of the rule. So `\t{\$1}' refers to the first token of the rule, `\t{\$2}' to the second, \dots Again attribute definitions are allowed to span several lines and strings must be specified in \C\ manner. \index{c@\C} For example, here again is the possible definition of a block in \PASCAL, now with an example attribute definition: % \begin{verbatim} block : BEGIN stmt_list END { $1 + $2 + force + $3 } ; \end{verbatim} \index{pascal@\PASCAL} The attribute of a \t{block} will therefore consist of the attributes of the \t{BEGIN} and \t{stmt\_list} tokens, joined together with a \fmt{force} command and the translation of the \t{END} token. The attribute definition may be omitted. If this is so, \pretzel will by default form the attribute of the produced symbol from the simple concatenation of the attributes on the right side of the rule. For instance % \begin{verbatim} stmt : block SEMI ; \end{verbatim} % means the same as: % \begin{verbatim} stmt : block SEMI { $1 + $2 } ; \end{verbatim} Of course you may also have empty right sides of a rule (to produce things out of nothing) or simply concatenate two or more rules resulting in the same symbol with a `\t{|}'. So the following are legal rules: % \begin{verbatim} stmt_list : { force } | stmt_list stmt SEMI { $1 + $2 + $3 + force } ; \end{verbatim} To end this subsection, we have to return to the {\em token declarations} section of the formatted grammar file. Here we have to insert a special line for every terminal token that appears in the grammar rules. These definitions are of the form `\t{\%token} \id{tokenname}'. This part of the formatted grammar file is owed to Bison and should be removed in subsequent versions. \subsection{Comments and Code} \index{Comments!in \pretzel\ input files} There is a very simple way of putting comments into the formatted token and formatted grammar files. This is done in a \CPP\ kind of manner by preceding the comment with a double slash (`\t{//}'). All characters between this sign and the end of the line are ignored by pretzel. \index{c++@\CPP} In both files you can put additional \CPP\ code before and after the definitions/grammar sections. If you want to insert code at the end of your file, you have to put a second `\t{\%\%}' on a line by itself and put the code behind it. \C/\CPP\ Code before the definitions/rules section has to be tied in with a `\%\{', `\%\}' pair. Inserting extra code will however only become interesting if these functions could be accessed from inside the attribute definitions of the grammar. This might be possible in a later version of \pretzel. \section{Making a Prettyprinter with Pretzel} So if you have specified the two necessary files that describe a prettyprinter for your favourite programming language called, say $P$ now, you will have a formatted token file called \t{p.ft} and a formatted grammar file called \t{p.fg}. To get your prettyprinter from these two files you have to successively invoke \pretzel, flex, Bison and your \CPP\ compiler. It is very convenient to use the \t{make} tool to support you with this task. There is a typical \t{Makefile} for such cases included in the \pretzel\ distribution. You can use it as a starting point for your own files. \index{makefile@\t{Makefile}} \index{flex}\index{Bison}\index{c++@\CPP} \subsection{Invoking Pretzel} The first step would be to produce the flex and Bison files using \pretzel. \pretzel\ is invoked by typing % \begin{verbatim} pretzel \end{verbatim} % at the command line. The full usage of \pretzel\ can be obtained using the \t{-h} option. It is: % \begin{verbatim} pretzel [-qtgdh] [-o outfile] (prefix | file1 file2) \end{verbatim} % Here's an explanation of the options: % \begin{description} \item[-q] Run quietly (no screen output). \item[-t] Process formatted token file only. \item[-g] Process formatted grammar file only. \item[-d] Run in debug mode (i.e.~print out debugging information on the screen while running). \item[-h] Show full usage. \item[-o outfile] Names of the produced output files begin with ``outfile''. \end{description} % The options \t{-t} and \t{-g} are mutually exclusive, i.e.~you can't choose both at the same time. \index{pretzel@\pretzel!options} The command line parameters have different meanings depending on whether one ore two names are given. If there is only one parameter, it specifies the prefix of both formatted token and formatted grammar files. The suffixes `{\tt .ft}' and `{\tt .fg}' are assumed. But if there are two parameters at the command line, \pretzel\ will take the first as full name of the formatted token file and the second as full name of the formatted grammar file. In this case, the output files will get a default name. The output files will have endings `{\tt .l}' (token file) and `{\tt .y}' (grammar file). \index{ft@\t{.ft} suffix} \index{fg@\t{.fg} suffix} \index{l@\t{.l} suffix} \index{y@\t{.y} suffix} \subsection{An Example Pretzel Session} So let's return to our initial example with our programming language $P$ for which we want to build a prettyprinter. To get both valid flex and Bison files we invoke \pretzel\ with: % \begin{verbatim} pretzel -o printp p \end{verbatim} % This will result in two new files, namely \t{printp.l} and \t{printp.y}. (The \t{-o} option defines the prefix of the output files.) The \t{.l}-file is the flex file and the \t{.y}-file is the Bison input. So now try % \index{pretzel@\pretzel!options} \index{options of@Options of \pretzel} \index{l file@\t{.l} file} \index{y file@\t{.y} file} \index{flex input} \index{Bison input} % \begin{verbatim} flex printp.l bison -d printp.y \end{verbatim} % to create \CPP\ code for your prettyprinter. After renaming the output files of flex and Bison to, say, \t{myscan.c} (flex) and \t{myparse.c} (Bison) you have to compile both. After compilation you will get object files that, together with the default headers, form the prettyprinter module. Other programs, that want to use the prettyprinter, only have to include the header file and be linked with the resulting object files. Figure \ref{simple-main} shows a minimal main program that reads from the standard input and outputs the prettyprinted code to the standard output. \begin{figure}[htbp] \begin{center} \leavevmode \begin{verbatim} /* * a minimal main program to test a pretzel prettyprinter */ #include #include "pparse.h" // include the header of the prettyprinter int main () { pparse(&cin,&cout); // call the prettyprinter function return(0); } \end{verbatim} \caption{A minimal main program that uses a \pretzel\ prettyprinting function.} \label{simple-main} \end{center} \end{figure} The \t{-d} option of Bison produces a so called `token header' file needed by the scanner (see figure \ref{detailed-concept} on page \pageref{detailed-concept}). It contains information about all of the non-terminal tokens that the parser knows of. The scanner expects to find it under the name \t{ptokdefs.h}, so you should rename this file to meet the scanner's expectations. \index{myscan@\t{myscan.c}} \index{myparse@\t{myparse.c}} \index{ptokdefs@\t{ptokdefs.h}} \index{Prettyprinter!token header file} \index{Token header file} \index{Bison!d option@\t{-d} option} \index{d option@\t{-d} option of Bison} \index{Common token header file} \index{Prettyprinter!header file} \index{Header file!of \pretzel\ prettyprinter} \subsection{Debugging the Prettyprinting Grammar} \index{Debugging the prettyprinting grammar} According to the prettyprinting grammar you specify, the generated prettyprinting function will parse the input text and try to prettyprint it. However, it sometimes may be impossible for the parser to parse the input according to the supplied rules. In such a case, the prettyprinted output may look a bit strange (a lot of stuff will be missing), but the prettyprinter will never stop or even issue an error. To fine-tune your grammar and look for the place it couldn't cope with, you can switch on a debugging feature that offers you are large amount of tracing information. You can switch it on by setting the external integer \t{yydebug} to a nonzero value. As soon as this is done and the parsing starts, you will see the standard Bison tracing reports. In addition to this, the attribute of every token read is displayed directly after the token name inside brackets when a new token is read. However, depending on the complexity of your grammar and the length of the input, parsing can take very long if you have the tracing feature switched on. So you should debug your prettyprinting grammar with small examples. \index{yydebug@\t{yydebug}} \subsection{Advanced Topics} \label{hacks} This section finally tells you some ways to fine tune your prettyprinter. \pretzel\ allows you to rename the prettprinting functions. This is done via \C\ preprocessor makros. Here's a list of makros with which you can influence the interfaces of prettyprinting scanner and parser. We'll see how to redefine them in a moment. \begin{description} \item[{\tt PPARSE\_NAME}] This makro is the name of the prettyprinting parser (`{\it pparse}' by default). \item[{\tt PSCAN\_NAME}] This makro holds the name of the prettyprinting scanner (`{\it pscan}' by default). \item[{\tt PSCAN\_NAME\_INIT}] This is the name of the initialiser function of the scanner (`{\it pscan\_init}' by default). \item[{\tt PTOKDEFS\_NAME}] This is the name of the common token header file that defines the token codes of the terminal tokens returned by the prettyprinting scanner (`{\tt ptokdefs.h}'' by default). \end{description} \index{pparse name@\t{PPARSE\_NAME}} \index{pscan name@\t{PSCAN\_NAME}} \index{pscan name init@\t{PSCAN\_NAME\_INIT}} \index{ptokdefs name@\t{PTOKDEFS\_NAME}} The names of these functions will be defined if the user doesn't have his own definition. For example, if you want to change the name of the prettyprinting scanner to `{\it foo}', you have to put lines like this into the declarations section of your formatted token file: % \begin{verbatim} %{ #define PSCAN_NAME foo %} \end{verbatim} % Note that you can only change the names of the functions, not other parts of their interface. (The `\verb+%{+' and `\verb+%}+' are necessary because the line in between is \C\ code.) The prettyprinting parser implicitly expects to have a scanner available for parsing under the default name. So if you are using a prettyprinting scanner with a different name you have to redefine the same makro again in the formatted grammar file. \section{Example (a Grammar for \PASCAL)} To end this chapter I will try to give a small impression about the looks of a formatted token and a formatted grammar file by giving a small example. The following inputs are excerpts of a prettyprinting grammar for something like \PASCAL. It was basically derived from Knuth's context sensitive grammar in his original \WEAVE\ program, but suits my own formatting preferences. The typesetter used in this example is \TeX\ using the macro definitions from Knuth's \t{cwebmac} macro package for \CWEB. Basicly, you could use any typesetter that has in-text procedural markup. The only thing you have to do is to write a macro package with a special tag for every format command and have the \pretzel\ prettyprinter output these special tag names instead of the current control sequences (\verb+\1+ \dots\ \verb+\7+). Using the {\tt cwebmac} package spared me from having to write my own set of commands and works fine for demonstration purposes. (See chapter \ref{five} on the problems of changing output formats.) Note that if you want to use the following code for playing around, you have to tell flex to create a case-insensitive scanner since reserved words are only noticed in lowercase. \index{pascal@\PASCAL}\index{weave@\WEAVE}\index{Example grammar} \index{Prettyprinter!example}\index{Knuth, Donald E.} \index{Context sensitive grammar}\index{tex@\TeX}\index{cwebmac@\t{cwebmac}} \index{cweb@\CWEB} The sequence `\verb+[...]+' denotes that parts are left out from the original file. \subsection{The Formatted Token File} \begin{verbatim} /* pretzel formatted tokens for simple PASCAL */ %% "<>" MATH { "$\\neqI$" } // not equal sign "<=" MATH { "$\\leq$" } // less or equal ">=" MATH { "$\\geq$" } // greater or equal ":=" MATH // assignment '([^']|'')*' SIMP // strings "(" OPEN ")" CLOSE "[" OPEN "]" CLOSE "*" MATH { "$\\ast$" } "," MATH { ** + opt9 } ".." MATH "." SIMP ":" COLON ";" SEMI "=" MATH "+" MATH "-" MATH "<" MATH { "$<$" } ">" MATH { "$>$" } "/" MATH // this to allow underscores in identifiers: "_"[a-zA-Z0-9]* ID_TYPE {"\\" + ** } [0-9]+ SIMP [0-9]*"."[0-9]+ SIMP and MATH {"\\AND "} array ALPHA {"\\&{array}"} begin BEG {force + "\n" + "\\&{begin}" } boolean SIMP {"\\&{boolean}"} case CASE {force + "\\&{case}" + cancel } const INTRO {force + backup + "\\&{const}"} div MATH {" \\&{div} "} do OMEGA {"\\&{do}"} downto MATH {"\\&{downto}"} else ELSE {"\\&{else}" } end END {"\\&{end}" } for ALPHA {"\\&{for}" } function PROC {big_force + backup + "\\&{function} " } if ALPHA {"\\&{if}" } integer SIMP {"\\&{integer}"} mod MATH {"\\&{mod}"} not MATH {"\\neg "} of OMEGA {"\\&{of} " + cancel } or MATH {"\\V "} procedure PROC {big_force + backup + "\\&{procedure} " } program PROC {big_force + backup + "\\&{program} "} readln SIMP {"\\&{readln}"} real SIMP {"\\&{real}"} record RECORD {"\\&{record}"} repeat BEG {force + "\\&{repeat}" } then OMEGA {"\\&{then}" } to MATH {" \\&{to} "} type INTRO {force + backup + "\\&{type}" } until UNTIL {force + "\\&{until}" } var INTRO {force + backup + "\\&{var} " } while ALPHA {force + "\\&{while}" } with ALPHA {force + "\\&{with}"} write SIMP {"\\&{write}"} writeln SIMP {"\\&{writeln}"} "{"[^}]*"}" COMMENT { "\\C{" + ** + "}" } [a-zA-Z][a-zA-Z0-9]* ID_TYPE // identifiers [\t\ \n] // eat up whitespace . // eat up other non matching characters \end{verbatim} \subsection{The Formatted Grammar File} \begin{verbatim} /* pretzel formatted grammar for simple PASCAL. */ %token SEMI %token BEG %token END %token MATH // token should only be used in math mode %token SIMP // other simple tokens %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %token COMMENT %token ID_TYPE %token RECORD %token CASE %% stmt_list : stmt // collect everything on a | stmt_list stmt // list of `statements' ; // what can statements be? stmt : COMMENT {cancel + $1} | proc // procedure heading | SEMI // empty statement {cancel + $1 + force } | BEG stmt_list END // a block { $1 + indent + force + $2 + cancel + outdent + force + $3 } | math // an expression ; math : MATH // build something like an | math math // `expression' | simp | COLON | OPEN decl_list CLOSE | RECORD stmt_list END ; simp : SIMP | identifier { "\\\\{" + $1 + "}" } ; identifier : ID_TYPE // put together identifiers | identifier ID_TYPE ; decl_list : math // parameter lists | INTRO math // for var-parameters | decl_list SEMI math {$1 + $2 + " " + $3 } | decl_list SEMI INTRO math // for var-parameters ; stmt : ALPHA math OMEGA stmt // if then/while do etc. { $1 + " " + $2 + " " + $3 + indent + force + $4 + outdent } | ALPHA math OMEGA stmt ELSE stmt // if then else {$1 + " " + $2 + " " + $3 + indent + force + $4 + outdent + force + $5 + indent + force + $6 + outdent } | CASE math OMEGA stmt_list END // case of end | BEG stmt_list UNTIL math // repeat until { $1 + indent + force + $2 + cancel + outdent + force + $3 + " " + $4 } ; proc : proc INTRO math SEMI {$1 + $2 + $3 + $4 + force} | PROC // procedure heading ; stmt : INTRO math SEMI // variable and type declarations {$1 + $2 + $3 + force} ; \end{verbatim} \subsection{Using the Generated Prettyprinter} The definitions in the previous section are sufficient to produce a prettyprinter for \PASCAL, that can handle most of the language features and formats them to suit my own preferences. As an example text I have chosen a simple \PASCAL\ routine to compute the square root of a given real number. It was written solemly for pleasure in my first year of study in Darmstadt to test one of the algorithms that were presented in a maths lecture. This is to demonstrate, that the example is by no means constructed to suit the demonstration purpose in this paper. I have tested the prettyprinter on various other \PASCAL\ texts. \index{pascal@\PASCAL}\index{Darmstadt} \subsubsection{The Pascal Input} This is what the plain \PASCAL\ source code looks like. \begin{verbatim} function Wurzel ( x : REAL ) : REAL; {Berechnet die positive Quadratwurzel von x} var x0, x1 : real; begin if x>=0 then begin x1:=x; repeat x0:=x1; x1:=(x0+x/x0)/2; until (x0 + abs(x0-x1) = x0); Wurzel:=x1; end else begin writeln('Fehler: Wurzel ist komplex!'); end; end; {Wurzel} \end{verbatim} \subsubsection{The Translation in \TeX} This is what the prettyprinter generated out of the \PASCAL\ text. Note again that the format commands are translated to suit the \t{cwebmac} macro package of the \CWEAVE\ system. The commands outside of the indicated area necessary to put \TeX\ into the right mood to format source code. The control sequences \verb|\1|\dots\verb|\7| refer to \fmt{indent} (1), \fmt{outdent} (2), \fmt{opt} (3, with the digit $n$ following directly), \fmt{backup} (4), \fmt{break\_space} (5), \fmt{force} (6) and \fmt{big\_force} (7). The commands \verb|\\| and \verb|\&| tag identifiers and reserved words, respectively. \begin{verbatim} \input cwebmac \B \Y % generated text begins here \7\4\&{function} \\{Wurzel}(\\{x}:\&{real}):\&{real}; \C{{Berechnet die positive Quadratwurzel von x}}\6\4\&{var} \\{x0},\39\\{x1}:\&{real};\6 \&{begin}\1\6\&{if} \\{x}$\geq$0 \&{then}\1\6 \&{begin}\1\6\\{x1}:=\\{x};\6\&{repeat}\1\6\\{x0}:=\\{x1}; \6\\{x1}:=(\\{x0}+\\{x}/\\{x0})/2;\2\6\&{until} (\\{x0}+\\{abs}(\\{x0}-\\{x1})=\\{x0});\6\\{Wurzel}:=\\{x1}; \2\6\&{end}\2\6\&{else}\1\6 \&{begin}\1\6\&{writeln}('Fehler: Wurzel ist komplex!'); \2\6\&{end}\2;\2\6\&{end};\C{{Wurzel}} % generated text ends here \end \end{verbatim} \subsubsection{The Formatted Output} This is what the actual formatted output looks like, if the above text is processed by \TeX. \begin{outp} % \1 indent % \2 outdent % \3 opt % \4 backup % \5 break_space % \6 force % \7 big_force % \8 no_indent % \& \res % \\ \id % \myforce\mybackup\res{function} \id{Wurzel}(\id{x}:\res{real}):\res{real}; \{Berechnet die positive Quadratwurzel von x\} \myforce\mybackup\res{var} \id{x0}, \id{x1}:\res{real};\myforce \res{begin}\myindent\myforce\res{if} \id{x}$\geq$0 \res{then}\myindent\myforce \res{begin}\myindent\myforce\id{x1}\ass\id{x};\myforce\res{repeat}\myindent\myforce \id{x0}\ass\id{x1}; \myforce\id{x1}\ass(\id{x0}+\id{x}/\id{x0})/2;\myoutdent\myforce\res{until} (\id{x0}+\id{abs}(\id{x0}-\id{x1})=\id{x0});\myforce\id{Wurzel}\ass\id{x1}; \myoutdent\myforce\res{end}\myoutdent\myforce\res{else}\myindent\myforce \res{begin}\myindent\myforce\res{writeln}('Fehler: Wurzel ist komplex!'); \myoutdent\myforce\res{end}\myoutdent;\myoutdent\myforce\res{end};\{Wurzel\} \end{outp} pretzel-2.0n-2/doc/project.report/manual.tex0000644000000000000000000000127005652777555017626 0ustar rootroot% % $Id: manual.tex,v 1.1 1994/10/24 18:39:38 gaertner Exp $ % % frame for the pretzel user's manual % % $Log: manual.tex,v $ % Revision 1.1 1994/10/24 18:39:38 gaertner % Initial revision % % \documentstyle[pretzel]{report} \makeindex % creates an .idx file for MakeIndex \pagestyle{headings} \begin{document} % read the titlepage \begin{titlepage} \input{manual-title} \end{titlepage} \tableofcontents \input{manual-intro} % introduction \input{chap2} % % At last we reach the index. The index was generated with the % MakeIndex program. \addcontentsline{toc}{chapter}{Index} \printindex % reads the .ind file and prints the index % Here we have reached the end! \end{document} pretzel-2.0n-2/doc/project.report/manual-title.tex0000644000000000000000000000074506236103216020723 0ustar rootroot % $Id: manual-title.tex,v 1.1 1994/10/24 18:44:56 gaertner Exp $ \null \vskip5cm \begin{center} \Huge ``Pretzel'' --- More than a Prettyprinter \vskip30pt \large Felix G\"artner \large TH Darmstadt (\today) \end{center} \vfill This manual only covers the very first version of \pretzel{}. Consult the \pretzel{}book for the latest version of \pretzel{} documentation. % % $Log: manual-title.tex,v $ % Revision 1.1 1994/10/24 18:44:56 gaertner % Initial revision % % pretzel-2.0n-2/doc/project.report/erklaerung.tex0000644000000000000000000000103305745507155020473 0ustar rootroot% erklaerung.tex 20 Apr 95 %------------------------------------------------------------ % % XXX % % [LaTeX] \documentstyle[german,a4,12pt]{article} \pagestyle{empty} \parindent0pt \begin{document} \null \vfill \hrule \section*{Erkl"arung} Ich versichere hiermit, da"s ich diese Arbeit ohne unzul"assige Hilfe und nur unter Benutzung der in der Arbeit angegebenen Literatur und Hilfsmittel angefertigt habe. \vspace{20pt} Darmstadt, den 27.~Februar 1995 \vspace{15pt} (Felix G"artner) \end{document} pretzel-2.0n-2/doc/project.report/report-intro.tex0000644000000000000000000001274205745446511021007 0ustar rootroot% $Id: report-intro.tex,v 1.4 1995/04/20 12:02:04 gaertner Exp gaertner $ % % $Log: report-intro.tex,v $ % Revision 1.4 1995/04/20 12:02:04 gaertner % Typo solemly = solemnly % % Revision 1.3 1995/02/24 08:49:26 gaertner % Changes first paragraph and introduced `execution' quote. % % Revision 1.2 1995/02/21 09:20:52 gaertner % Changed \mkWEAVE to \pretzel. % % Revision 1.1 1995/02/21 09:17:42 gaertner % Initial revision % % \chapter*{Introduction} \addcontentsline{toc}{chapter}{Introduction} \begin{quote} ``Any programmer who fails to comply with the standard naming, formatting or commenting conventions should be shot. If it so happens that it is inconvenient to shoot him, then he is to be politely requested to recode his program in adherence to the above standard.'' \cite{Ledgard77} \end{quote} \noindent Recently, when discussing an assignment in a course on software engineering, the lecturer addressed the auditorium and stressed the fact that he would reject any code that wasn't properly indented. This was very striking for me since I have never considered proper indentation to be a major problem for any programmer. I always had assumed that everybody was already doing so. But I was wrong. Luckily, insufficient program formatting in this course didn't result in any executions as the above quote might suggest. But this note pointed to a problem that I have never been really aware of, possibly because I have actually learned to write programs in a to date non-standard way, i.e.~using a \WEB. In common words a {\em web} is a fine net made by a spider to catch insects. Since 1984, `\WEB' is also known as another name for a {\em literate program}, a highly documented program designated for the eye of a reader and not solemnly for execution by a computer; \WEB s are meant to be {\em works of literature}. This is the basicly new idea of {\em literate programming}, a programming style first introduced by Donald E.~Knuth in 1984~\cite{Knuth:CJ-27-2-97}. This concept is a new attempt to promote understandability and readability of a program's source code. With this style, the programmer can be ``regarded as an essayist, whose main concern is with exposition and excellence of style''. Instead of writing a program sufficing the rigid rules of a compiler, the programmer is free to choose the manner of presenting the ideas and algorithms of his program. This change of attitude lifts normal computer programs up to become \WEB{}s. \index{Literate programming} \index{Knuth, Donald E.} To turn these ideas from theory to practice one needs special tools to bypass the restrictions imposed by normal compilers. One of these tools processes the \WEB\ and turns it into a well formatted, high quality document (including proper indentation) that serves as a source code documentation. A system routine performing this task is usually referred to as a \WEAVE\ processor. This processor {\em weaves the web}, i.e.~it improves the appearance of the \WEB. In most cases, \WEAVE{}ing is only the first step towards the final document: The second step normally consists of using a professional typesetter program to produce code for output devices such as high resolution graphic displays or laser printers. \index{weave@\WEAVE} \index{Typesetters} Normally \WEAVE\ not only enhances the readability of the informal text (i.e.~commentary) in the \WEB; it also improves the appearance of the formal text, i.e.~the small parts of source code that are scattered all over the \WEB. This work is commonly called {\em prettyprinting}. The prettyprinting of the source code is normally the most intricate part of every \WEAVE\ program. This is due to the fact that the problem of prettyprinting is highly language dependent and that---being mostly a matter of personal taste---prettyprinting has to follow a lot of small details to make the output look nice. \WEAVE\ systems normally have a built in prettyprinting algorithm designed by the program author that reflects mainly his opinion of how to space instructions of the underlying programming language. \index{Prettyprinting} \index{Personal taste} \bigskip\noindent This paper states that together with the literate program the way of prettyprinting should also be an input parameter to a \WEAVE\ system. To enable this idea, the author has written a program called \pretzel\ that automatically generates a prettyprinter from a general description of the programming language to be prettyprinted. In this paper I will present this program and discuss several issues related with the topic of prettyprinting, as well as giving an overview of how this program may be used in future projects on literate programming. \index{pretzel@\pretzel} This text follows a course that can be described as ``from theory to practise''. It starts by giving a rather long and theoretical overview over the area of prettyprinting (chapter \ref{one}) and then turns to a more user orientated introduction to the \pretzel\ program (chapter \ref{two}, the \pretzel\ user's manual). The end of the more abstract part (chapter \ref{three}) is devoted to the issue of literate programming and the role that \pretzel\ may play in it. The more practical part is centered around a programmer's point of view. It discusses the design of the \pretzel\ system (chapter \ref{four}) and states future work that may be done to improve the system (chapter \ref{five}). The most ``practical'' part follows in the appendix where you actually will see parts of the program code, i.e.~some specifications of \pretzel\ modules. pretzel-2.0n-2/doc/project.report/chap1.tex0000644000000000000000000015365506254321650017340 0ustar rootroot% % $Id: chap1.tex,v 1.6 1995/04/20 13:32:31 gaertner Exp $ % % $Log: chap1.tex,v $ % Revision 1.6 1995/04/20 13:32:31 gaertner % small corrections. % % Revision 1.5 1995/04/20 12:14:56 gaertner % Small corrections proposed by JS. % % Revision 1.4 1995/02/24 09:04:03 gaertner % A few typos. % % Revision 1.3 1995/02/23 10:26:04 gaertner % Final revision (including figures and index). % % Revision 1.2 1995/02/21 09:12:45 gaertner % First and final full rewrite of this chapter. Have to go over % the details later. % % Revision 1.1 1995/02/16 11:11:08 gaertner % Initial revision % \chapter{On Prettyprinting} \label{one} The term {\em prettyprinting} means the rearrangement of a program's source code to illuminate it's logical structure and thus enhance readability. The term goes back to Henry Ledgard and his ``Programming Proverbs''~\cite{Ledgard75}. Prettyprinting has become a field of interest because many of todays popular programming languages are so called ``free-format'' languages, where there are basically no column-position or line-boundary restrictions on statements, declarations, or comments. \index{Prettyprinting}\index{free format@``free format'' languages} \index{Ledgard, Henry F.} As a matter of fact, formatting and all other aspects of readability depend heavily on personal taste and skill. This has lead to a wide range of suggestions and standards concerning the formatting of programming languages, especially for the \PASCAL~\cite{Jensen85} language~\cite{Arab92,Bailes84,Bates81,Bond79,Crider78,Grogono79,Gustafson79,Heckert85,Ledgard77,Marca81,Peterson77,Mohilner78}.\label{formattingstandards} The consistency of these proposals has also enabled construction of automatic formatting algorithms and tools that are usually called {\em prettyprinters\/} (or {\em indenting programs\/}). In the literature general examples of prettyprinters have been presented among others for the languages \ALGOL~\cite{McKeeman65,Scowen71}, PL/I \cite{Conrow70}, \LISP~\cite{Goldstein73,Hearn79,Waters83,Waters92}, Ada \cite{Norris84}, and of course for \PASCAL~\cite{Hueras77,Jackel80,Bates81,Winter89,Arab92}. \index{Personal taste}\index{Taste!personal}\index{pascal@\PASCAL} \index{Formatting standards}\index{Formatting algorithms} \index{Prettyprinters!for other languages} \index{Indenting programs|see{Prettyprinters}} \index{algol@\ALGOL}\index{PL/I}\index{lisp@\LISP}\index{Ada} \index{pascal@\PASCAL} However, technological advance in the area of automatic typesetting has led to a set of powerful formatting tools called {\em typesetters}, or {\em typesetting systems}, of which \TeX~\cite{TeXbook} is maybe the most apparent to computer scientists. These tools allow the preparation of documents in high quality suited for publication. Among the features of these systems are automatic line- and page-breaking, powerful macro-processing facilities and convenient devices for typesetting mathematical formulas. Seen in this light, automatic program formatting is only a simple instance of automatic typesetting \cite[p.~652]{Rose81}. So prettyprinting algorithms that rely on professional typesetters can be simpler and produce better results at the same time, because a lot of the formatting problems (e.g.~alignment, line-breaking, typesetting mathematical formulas) can be taken on by the typesetter. \index{Automatic typesetting}\index{Typesetters}\index{Typesetting systems}\index{tex@\TeX}\index{Program formatting} \smallskip In this chapter I will now present the prettyprinting algorithm that is used in the \pretzel\ system. It is a simple, but sophisticated method that relies on a typesetter. I have chosen a rather straightforward approach to this presentation using a lot of examples and leaving the discussion of this algorithm to the very end of this chapter. \section{Prettyprinting with Format Commands} \label{fmt-commands} \index{Format commands!explained|(} The prettyprinting method presented here can be called {\em prettyprinting with format command primitives} and goes back to a similar method used by Knuth in his original \WEAVE\ system for \PASCAL\ (see section \ref{relatedwork} for details). Like most other prettyprinting algorithms this method functions similar to a {\em compiler}, i.e.~an input file is processed and translated into an output file according to special rules. Here, the input file is the patch of source code that shall be prettyprinted and the output file is the text suited for the typesetter. The translation rules represent the special way in which source code should be formatted. \index{pascal@\PASCAL}\index{weave@\WEAVE}\index{Knuth, Donald E.} \index{Compilers!and prettyprinters} The main assumption is that we have a text formatter that uses {\em control sequences\/} (or {\em tags\/}) inside the actual text body for specifying all the different ways of formatting (such as fonts, indentation, spacing, etc.). Another term for this way of formatting control is {\em in-text procedural markup\/} and systems using this technique are commonly called {\em document compilers} (though this might only refer to the way they work, not to viewing text processing as programming). Common examples of such typesetting systems are \TeX\ and the \UNIX\ tools Nroff/Troff. \index{Control sequences}\index{Tags}\index{In-text procedural markup} \index{Markup}\index{Procedural markup}\index{Document compilers} \index{Compilers!for documents}\index{tex@\TeX}\index{unix@\UNIX} \index{Nroff}\index{Troff} So what does the prettyprinting algorithm presented here actually do? During the processing of the input the only thing it does is to enrich the stream of incoming information with special control sequences that I will call {\em format commands} (or {\em format command primitives}). These commands are tags that are left for the typesetter to interpret. The set of format commands used here is basically the initial set used by Knuth. \index{Knuth, Donald E.!command set by} To understand this procedure we don't have to go into the special nitty-gritty details now. This will be done excessively in the following chapter. It probably will be more instructive to introduce the command set by way of example. \index{Nitty-gritty details}\index{Details!nitty gritty} Finally a word about the notation: In the following examples of input text the format commands will be set in italics whereas normal strings will be given in typewriter type. The corresponding output text of the examples will reflect the input in a way similar to the output obtained using \TeX\ as typesetter and the ``normal'' interpretation of the format commands. \index{Typesetting conventions}\index{Conventions!of typesetting} \index{tex@\TeX}\index{Interpretation of format commands} \index{normal interpretation@``normal'' interpretation} \subsection{Controlling the Amount of Indentation} So let's now have a look at a few small examples of how prettyprinting works with the so called format commands. The first interesting thing to consider is the contol of indentation. Suppose we want to prettyprint a simple \res{while}-\res{do}-statement of \PASCAL\ and we want to indent the body of this statement a bit from it's header keyword. The plain \PASCAL\ text of our first example looks like this: % \begin{inp} while (ic) and (str\_buf\_ptr<=buf\_size) do \end{inp} Inserting \fmt{break\_space}s before and after the ``\t{and}'' would seem to be a good solution to this line-breaking problem. But breaking the line after the ``\t{and}'', say, would result in % \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do} \end{outp} % what of course is intolerable. We want a long continuous line to be indented a little if it is broken, like in: \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myindent\myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do} \end{outp} % Using the \fmt{indent}, \fmt{outdent} and \fmt{force} primitives is no solution in this case. This becomes clear if you look at the \res{while}-loop followed by its body: % \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myindent\myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do}\myforce \res{begin}\myforce \dots\myforce \res{end} \end{outp} % In case of a line break within a statement the indentation has to be sufficiently different from the normal \fmt{break-space}d or \fmt{force}d indentation. So the answer is: More space! Therefore we need a new primitive, namely the {\em optional line break} command \fmt{opt}. There are ten different \fmt{opt}s that specify the badness of a line break at the point of it's occurence. They are called \fmt{opt0}, \fmt{opt1},\dots, \fmt{opt9}. A smaller number encourages line breaking at this point more than a higher number. So \fmt{opt0} will nearly always lead to a line break whereas \fmt{opt9} leads to a line break only if there is no \fmt{opt0},\dots, \fmt{opt8} primitive somewhere near and the line {\bf has} to be broken around this point. (In \TeX\ terms the digit $n$ in the name of the \fmt{opt} command specifies the penalty associated with this break point. The penalty in the default interpretation of \fmt{opt} is about $10\cdot n$.) \index{opt@\fmt{opt}}\index{Format commands!opt@\fmt{opt}} \index{Optional line-break} So the \fmt{opt} command denotes an optional line break with the continuation line indented a little more with respect to the normal indentation. Returning to our example from above we should therefore say % \begin{inp} while (str\_buf[str\_buf\_ptr]<>c) and \fmt{opt4} (str\_buf\_ptr<=buf\_size) do \fmt{indent} \fmt{force} begin ...\fmt{force} end \end{inp} % depending on whether we rather liked a line break before or after the ``\t{and}''. This would then yield the correct way of formatting, as in: % \begin{outp} \res{while} $(\id{str\_buf}[\id{str\_buf\_ptr}]<>\id{c})$ \andsign \myindent\myindent\myindent\myforce $(\id{str\_buf\_ptr}\leq\id{buf\_size})$ \res{do}\myoutdent\myoutdent\myforce \res{begin}\dots\myforce \res{end} \end{outp} % Note however that a \fmt{break\_space} is always a better place to break a line than an optional line break denoted by \fmt{opt}. % \index{opt and break space@\fmt{opt} and \fmt{break\_space}} \subsection{Additional Commands} By choosing the examples in the way above, I hope to have made clear that the format commands presented so far are sufficient to format program text of any block structured programming language in a manner according to most of the formatting standards referenced in the introduction of this chapter on page~\pageref{formattingstandards}. Readers, who are not yet convinced, are put off until section \ref{relatedwork}, where the evolution of this method is reconstructed. % \index{Command set!sufficiency} However, the list of format commands is not yet complete. There are still a few more primitives to learn, but they are not as important as the other commands that were presented up to this point. The following primitives were introduced to achieve better formatting results in special situations. The first one is called \fmt{backup} and denotes a little negative horizontal space. This command must be preceded by a \fmt{force}, because it doesn't make sense to backup within a line if it's beginning has already been output. So the two commands ``\fmt{force}, \fmt{backup}'' appearing in a row can be seen as a short form for the sequence ``\fmt{outdent}, \fmt{force}, \fmt{indent}''. The \fmt{backup} command is used in cases where statements are preceded by labels or simply where a line should stick out to the left a bit in order to emphasize it. % \index{Format commands!backup@\fmt{backup}} \index{backup@\fmt{backup}} The next additional command is called \fmt{big\_force}. As the name implies this primitive acts like a \fmt{force}, but only on a bigger scale. \fmt{big\_force} not only forces a line break; it also inserts a little extra vertical space after the break. You can use the \fmt{big\_force} primitive to separate two adjacent lines that semantically do not belong together, like two function declarations. % \index{Format commands!big force@\fmt{big\_force}} \index{big force@\fmt{big\_force}} If you are trying to typeset \C\ or \CPP\ programs, you will need a feature to typeset so called preprocessor directives. These are commands beginning with a $\#$ that can influence the source code before compilation. Normally these lines appear beginning at the left margin so we want a command that can be used to typeset lines like this. This command is called \fmt{no\_indent}. It causes the {\bf current} line to be printed flushleft. So if you want to prettyprint a \C\ or \CPP\ preprocessor line, you should say % \index{c++@\CPP} \index{c@\C} \index{Preprocessor} \index{c preprocessor@\C\ preprocessor} \index{Format commands!no indent@\fmt{no\_indent}} \index{no indent@\fmt{no\_indent}} % \begin{inp} \fmt{force} \fmt{no\_indent} $\#$PREPROCESSOR\_DIRECTIVE \fmt{force} \end{inp} % and the line following this directive will be indented as much as the line before the directive. %cancel Finally the last command of the present command set is called \fmt{cancel}. To understand this command I have to mention a tricky detail of the presented algorithm that I have omitted in the intoduction of this section: There I said that format commands are simply output by the prettyprinter one by one just like strings, only that they are ``marked'' as typesetting commands. Actually the prettyprinter also does a little bit of interpretation in advance. But these exceptions from the rule can be caught in two phrases\label{two-phrases}. The first one is of global importance and the second one is related to the \fmt{cancel} command: \index{Format commands!cancel@\fmt{cancel}} \index{cancel@\fmt{cancel}} \index{Exceptions} \index{Preprocessing of format commands} \index{Tricky details} \begin{enumerate} \item A sequence of consecutive \fmt{break\_space}, \fmt{force}, and/or \fmt{big\_force} commands is replaced by a single command (the maximum of the given ones). \item The \fmt{cancel} command cancels any \fmt{break\_space}, \fmt{opt}, \fmt{force} or \fmt{big\_force} command that immediatly precede or follow it and also cancels any \fmt{backup} command that follows it. \end{enumerate} So it seems that the \fmt{cancel} command is a command that mixes everything up again after we have put everything into a neat and tidy form! But this only seems so. The interpretation done by the prettyprinter according to the two rules stated above, was introduced to be more generous and more flexible with the placement of format primitives into the source code. Because, after all, the format commands will not be inserted by hand (as the reader might think after viewing the examples given above), but they will be inserted automatically by the prettyprinter according to a {\em prettyprinting grammar}. % \index{Flexibility} \index{Prettyprinting grammar} \index{Format commands!explained|)} \subsection{Summary of Format Commands} \index{Format commands!summary} \index{Summary of format commands} Table \ref{command-table} shows a complete list of all the format command primitives introduced in this chapter. The only command that wasn't mentioned up to now is the \fmt{null} primitive that serves as a neutral (or empty) command. \index{Format commands!null@\fmt{null}} \index{null@\fmt{null}} \begin{figure}[htb] \begin{center} \begin{tabular}{lp{7cm}} \fmt{null} & empty command \\ \fmt{indent} & indents the next line a little more \\ \fmt{outdent} & takes back the last indentation (de-indent) \\ \fmt{force} & forces a line break \\ \fmt{break\_space} & denotes a possible space for a line break \\ \fmt{opt$\,n$}, $n \in \{0,\dots,9\}$ & denotes an optional line break with the continuation line indented a litte with respect to the normal starting position. This line break will score a penalty of $10n$.\\ \fmt{backup} & denotes a small backspace\\ \fmt{big\_force} & forces a line break and inserts a little extra space \\ \fmt{no\_indent} & causes the current line to be output flushleft\\ \fmt{cancel} & obliterates any \fmt{break\_space}, \fmt{opt}, \fmt{force} or \fmt{big\_force} command that immediatly precedes or follows it and also cancels any \fmt{backup} command that follows it. \end{tabular} \end{center} \caption{List of format command primitives} \label{command-table} \end{figure} \subsection{The Prettyprinting Grammar} \label{grammar-idea} The functionality of the format command primitives from the previous subsection is only half of the work of the prettyprinting process. The second point is the way how these commands are automatically inserted into the source code. This is done using a so called prettyprinting grammar. To get an idea of how formatting with such a grammar works, I will give a short and low-level introduction now. The exact way in which this grammar is specified to work with \pretzel\ is a topic that will be discussed in detail in chapter \ref{three}. \index{Prettyprinting grammar} The idea of formatting with a prettyprinting grammar is to insert format commands during a bottom up parse of the programming language text. Taking, say, a context free grammar to describe something similar to \PASCAL, a grammar rule for a \res{while} loop might look like this: % \index{pascal@\PASCAL}\index{Context free grammar} % \begin{inp} WHILE expr DO stmt $\longrightarrow$ stmt \end{inp} % This means that a \t{WHILE} token followed by an expression, followed by a \t{DO} token, followed by a statement can be reduced to a statement again (and can be used for example within a second \res{while}-loop that surrounds it). Here the tokens \t{WHILE} and \t{DO} are non-terminal symbols of the grammar and \t{expr} and \t{stmt} are terminals. The simple trick that converts a normal grammar to a prettyprinting grammar goes back to Knuth's idea of ``attribute grammars''. In such a grammar every token has a so called {\em translation} that reflects certain semantic properties about it. (For example, the translation of an identifier token could be its name.) The translations of tokens are constructed from the translations of the tokens that it has reduced. The translation of the \t{stmt} token in our example would be put together from the translations of the \t{WHILE}, \t{expr}, \t{DO} and the other \t{stmt} token on the left side of the rule. \index{Knuth, Donald E.}\index{Attribute grammar}\index{Translation} A prettyprinting grammar is an attribute grammar. As seen in the previous section, it is our aim, to insert format commands into certain spaces within syntactic constructs of the programming language. Now think of the translation of a token to be the actual printed output of the token, that can be sent to a typesetter. Inserting format commands into the translation can be achieved by defining the special ways of how to build the translation of certain constructs during rule reduction. So, for instance we could say: ``Every time I reduce a \t{WHILE}-loop to a \t{stmt}-token, I should insert an \fmt{indent} and an \fmt{outdent} format command around the body of the \res{while}-loop. Additionally a \fmt{force} command should be inserted behind the \fmt{outdent}.'' This can be expressed by the following notation, that uses ``pseudo-tokens'' (that can be imagined of being non-terminal tokens that match the empty string): % \index{Prettyprinting grammar}\index{Pseudo tokens} % \begin{inp} WHILE expr DO \fmt{indent} stmt \fmt{outdent} \fmt{force} $\longrightarrow$ stmt \end{inp} % This rule states, that the statement controlled by the \res{while} loop should be indented a little from it's header if this statement happens to begin on a new line. The indentation is taken back (\fmt{outdent}) and there will always be a line break at the end of such a statement (if the \fmt{force} isn't \fmt{cancel}ed). As a matter of fact, this way of expressing the formatting of a programming language within its own grammar is very intuitive and powerful. It would be possible to code a prettyprinting grammar in this way into machine readable form. However, for reasons of simplicity of design the author has chosen to use a slightly different way of expressing such grammars in \pretzel, but this will be discussed in the following chapter (see also chapter \ref{five} on future work). The fact that such a grammar will solemnly be used to create a ``prettyprinted'' translation of a bit of source code has a great impact on the resulting grammar. In \PASCAL\ for instance, \res{for}-, \res{while}- and \res{else}less \res{if}-statements are normally formatted in a very similar way; so the grammar mustn't distinguish between the three constructs. This results in prettyprinting grammars that can be quite different from the normal grammars of the programming languages. Mostly they are smaller. But if you want to design a prettyprinting grammar yourself, it is always easier to start with a normal language syntax and simply enhance every rule to suit the occasion. \index{Translation}\index{pascal@\PASCAL} \section{A Short History of Prettyprinting} \label{relatedwork} In this section I will give a brief chronological overview over the area of prettyprinting, try to structure the field, and will show, how the present system fits into it. \index{History of prettyprinting}\index{Prettyprinting!history} \subsection{Historical Notes} The prettyprinting of code has a long tradition that not only originates from the compulsion to typeset programs for publication. The readability or even the sheer beauty of a prettyprinted algorithm have also been a key motivation to this part of computer science. \index{Tradition}\index{Beauty} The first people to call special attention to formatting issues were probably Peter Naur, Myrtle Kellington and William McKeeman. While Myrtle Kellington, as executive editor of ACM publications, helped to develop high quality programming-language typography standards, Naur was the first to include such formatting standards into his report on the \ALGOL~60 language \cite{ALGOL-Report} and McKeeman was the first to present a prettyprinting algorithm for it \cite{McKeeman65}. This reaches back to the early 60s. In fact, McKeeman`s algorithm is the first actual prettyprinter to be found in the literature. Its purpose was % \index{Naur, Peter}\index{Kellington, Myrtle}\index{McKeeman, William} \index{ACM}\index{algol@\ALGOL}\index{Prettyprinter!first} % \begin{quote} ``[\dots] to edit \ALGOL~60 text that is difficult to read because, for example, the \ALGOL\ has been transcribed from printed documents, or written by inexperienced programmers [\dots]'' \end{quote} % Later, other prettyprinters were presented for PL/I~\cite{Conrow70}, \LISP~\cite{Goldstein73}, and finally \PASCAL~\cite{Hueras77}. These systems simply looked at the input text searching for special keywords. When encountering a keyword (which could be a \res{begin} or an opening brace, for example) a certain action would be triggered which would result in a line break, change of indentation, etc. \index{PL/I}\index{lisp@\LISP}\index{pascal@\PASCAL} \index{Prettyprinters!running on keywords} In these first approaches to the issue of prettyprinting the basic actions that prettyprinting includes were already visible. These concern (in order of importance):\footnote{In the late 70s there was one additional point on this list, namely the introduction of `connector lines' into the prettyprinted output \cite{Clifton78,Ramsdell79}. But this method hasn't found too much support since.} \index{Connector lines}\index{Prettyprinters!basic actions} \index{Basic actions of prettyprinters} \label{basic-actions} \begin{itemize} \item indentation and folding (i.e.~determining line breaks) of source code \item the additional spacing of syntactic constructs (like expressions) \item using additional typographic means (e.g.~different fonts) \end{itemize} \index{Indentation}\index{Folding}\index{Spacing!additional} \index{Additional spacing} The main disadvantage of the early systems was their language dependence. The style of prettyprinting was hard-wired into the system, which was basicly a big ``case'' switch over all known constructs that were to be treated specially. The main advantage of them, however, was their simplicity and their error handling capabilities (which is also the reason why such and similar tools are still widely used today). But it was soon clear that this approach wasn't adequate and that structural changes had to be made to the concept. \index{case@``case'' construct}\index{Early prettyprinters} \index{Prettyprinters!early systems} In their paper titled ``A One-pass Prettyprinter'' \cite{Hearn79} Hearn and Norman introduce a fundamentally new idea into this area. They simplify the whole concept of prettyprinting by introducing structure. \index{Hearn, A. C.}\index{Norman, A. C.} \begin{quote} ``The new method that we propose here will be described in terms of a pair of coroutines. One of these will be responsible for producing a stream of characters that represent the program being printed, the other makes decisions about how these characters should be displayed.'' \cite[p.~52]{Hearn79} \end{quote} This is a fundamental distinction, namely that between {\em formatting policy\/} and {\em formatting algorithm\/} \cite{Bailes84} and is a vital step on the road to language independence.\footnote{This idea however has also introduced a slight blur in the terminology, as some authors refer to prettyprinting as consisting only of the actual ``printing'' on paper (i.e.~the formatting algorithm) \cite{Oppen80,Jokinen89} and others still mean the entire process.} \index{Formatting policy}\index{Formatting algorithm} \index{Algorithm-policy distinction}\index{Policy-algorithm distinction} \index{Coroutines} A problem that arises from this separation is: how do the two coroutines communicate? Hearn and Norman use a simple FIFO buffer in which the first coroutine inserts text and ``special markers'' that indicate its decisions on the policy. These markers were mainly special blanks that indicate possible line breaks. \index{FIFO buffer}\index{special markers@``special markers''} \begin{quote} ``The markers will contain enough information for the formatting process to discover what level of indentation would be appropriate to use were a line break to be inserted at that point.'' \end{quote} This resembles a special kind of `communication protocol' and is the first hint to a thing that I have called `format command primitive' throughout this chapter. Other authors \cite{Jackel80,Oppen80,Waters83,Blaschek89,Rubin83,Rose81,Jokinen89} have taken up this idea and have introduced different sets of format commands that change and increase the communication facilities between these two processes. The two most elaborate to date are those of Rubin \cite{Rubin83} and that of Knuth and Levy \cite{Knuth:CSS93}, that is used here. \index{Communication protocol}\index{Format commands} \index{Rubin, Lisa F.}\index{Knuth, Donald E.}\index{Levy, Silvio} The separation introduced by Hearn and Norman is an example of `separation of concerns': the language dependent parts of prettyprinting are separated from the actual typesetting issues that arise, when putting text to paper. Blaschek and Sametinger \cite{Blaschek89} call this a distinction between ``language dependent front end and language independent back end''. \index{Hearn, A. C.}\index{Norman, A. C.}\index{Separation of concerns} \index{Language (in)dependence}\index{Prettyprinting!language (in)dependence} \index{Blaschek, G.}\index{Sametinger, J.} \index{Front end}\index{Back end}\index{Language dependent front end} \index{Language independent back end} \subsection{The Language Dependent Front End} The earliest suggestions how to build the language dependent front end go back to Oppens fundamental paper on prettyprinting \cite{Oppen80}. Though his main concern is the language independent back end, he makes suggestions about the ``preprocessor'' that should drive it. The main idea is to make a full syntactic parse of the prettyprinted code and to use the resulting parse tree to drive the prettyprinter. The format commands are either assumed to be implicit in the tree (i.e.~every single branch is treated as a structural block) or they are explicitly inserted into the tree during the parse. Oppen writes: % \index{Oppen, Derek C.}\index{preprocessor@``preprocessor'' for prettyprinting} \index{Parse tree}\index{Implicit format commands}\index{Explicit format commands}\index{Format commands!explicit}\index{Format commands!implicit} % \begin{quote} ``First, notice that the information needed by the prettyprinter can often conveniently be represented directly in the grammar [\dots]. We modify the grammar of the language to contain prettyprinting information as above, where [\dots] [the formatting commands] are nonterminals mapping only the empty string.'' \cite[p.~475]{Oppen80} \end{quote} This aspect has at last enabled people to use formal methods to describe layout rules. Mateti's paper \cite{Mateti83a} is another approach in the same direction and is the first to adapt this method to \PASCAL.\footnote{ It is interesting that Mateti's solution was the result of formalization (due to verification needs) and that Oppen's proposals emerged from the language independent nature of his approach.} The fact that rules for layout and grammar are often closely related \cite{Leinbaught80} also is a strong indication that this method is in fact adequate. The trend towards formal specification in this area has indeed been ``very fortunate'' \cite{Woodman86} and has also proved to be useful in other areas, such as syntax-directed editors \cite{Rubin83}. \index{Formal methods}\index{Mateti, P.}\index{pascal@\PASCAL} \index{Oppen, Derek C.} \index{Syntax-directed editors}\index{Editors!syntax directed} To this end Rose and Welsh \cite{Rose81} have advocated the integration of format rules within the language syntax on the language design level. They state that ``program format decisions [should be put] in the domain of the language's designer, rather than its several implementators or numerous users, which implies uniformly formatted programs of improved readability and therefore usability.'' \cite[p.~651]{Rose81} Their idea does {\em not} try to impose rigid formatting rules on users of existing or future languages. Instead they propose a metasyntax and a set of guidelines that constrain and direct the language designer in the placing of format commands. These format commands include commands for indentation, as well as for line breaks and optional line breaks (so called ``fold options''). The metasyntax and the guidelines only effect rather global issues of formatting but ensure consistency across language borders. They also present a folding algorithm that implements the format commands from their list. \index{Rose, G. A.}\index{Welsh, J.}\index{Rigid formatting rules} \index{Metasyntax (Rose and Welsh)}\index{Guidelines (Rose and Welsh)} \index{Folding algorithm (Rose and Welsh)} This last approach by Rose and Welsh is currently the `state of the art' in program layout issues. Woodman has published a thorough discussion of this scheme and has proposed refinements \cite{Woodman86} that however do not alter the main points. It is an approach that in some way surpasses the area of prettyprinting in that it forces the formatting grammar to be equal to the language reference grammar. However, Knuth shows that a prettprinting grammar can be much simpler than a full-size language grammar, because it is able to treat semantically different contructs equally as they are formatted in the same way (e.g.~\res{if}, \res{for} and \res{while} statements). \index{State of the art}\index{Woodman, M.}\index{Knuth, Donald E.} \subsection{The Language Independent Back End} The language independent back end implements the formatting algorithm. It actually makes the formatting decisions that the formatting policy has outlined and communicated to it via the format commands. The main concern of most algorithms is line breaking (or {\em folding\/}). The proposals by Rose and Welsh \cite{Rose81} and Oppen \cite{Oppen80} have been the most influential ones on other systems \cite{Waters83,Jokinen89,Blaschek89} in the literature. However, in both articles the authors refer to the future of their proposals for the formatting algorithm: % \index{Formatting policy}\index{Folding}\index{Language independent back end} \index{Rose, G. A.}\index{Welsh, J.}\index{tex@\TeX} % \begin{quote} ``The changes advocated must be seen in the light of current technological advances. Automatic program formatting is a very simple instance of automatic typesetting, as that provided by Knuth's TEX system for technical or mathematical text.'' \cite[p.~652]{Rose81} ``It [the algorithm] is not, however, as sophisticated as it might be, and certainly cannot compete with typesetting systems (such as TEX) for preparing text for publication.'' \cite[p.~466]{Oppen80} \end{quote} As the \WEB\ system shows, \TeX\ has been used as a back end for a prettyprinter, but it has remained the only one that I am aware of. This leads to the question, why so little prettyprinters faciliate typesetters as back ends for their output? This question is very striking, as typesetters offer powerful capabilities, and for example, \TeX's line breaking algorithm has been advocated to be very suitable for exactly this task \cite{Knuth-Plass81}. \index{web@\WEB}\index{tex@\TeX} Oppen gives an answer to this in his paper: % \begin{quote} ``However, it [the algorithm] seems to strike a reasonable balance between sophistication and simplicity, and to be appropriate as a subcomponent of editors and the like.'' \cite[p.~466]{Oppen80} \end{quote} \noindent It is surely the question whether you are prettyprinting on screen or preparing a publication. But the other part of the answer is maybe not so obvious and has to do with the traditional fears in the programming community. A lot of prettyprinters have been built as parts of larger programming environments and were constituent parts of this larger system. A lack of modularity in the design (as for example the fundamental distinction presented in these sections and visialized in figure \ref{pp-concept}) often makes the resuing of subcomponents impossible. The prettyprinters hide somewhere in the larger system and are difficult to extract. \index{Reuseability}\index{Modularity} Another point is that an old habit of programmers is their strive for independence. They do not want their systems to rely on other systems. But this habit is hopefully getting less frequent today. \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/pp-concept.latex} \end{center} \caption{The module structure of modern prettyprinters} \label{pp-concept} \end{figure} \subsection{The Set of Format Commands} The format commands passed between the front end and the back end of the prettyprinter are the only means to convey the formatting policy to the actual formatter (see figure \ref{pp-concept} that visualizes the modularity of a prettyprinter). This means that every typesetting feature must be expressible in them. In conjunction with this work it is important to ask, if the command set provided in the current \pretzel\ system is sufficient to format every desired feature that we can possibly think of. The answer is clearly `No!', as there still are open prettyprinting problems. We will have a look at them later. But just how sufficient is the command set? \index{no@``No''}\index{Sufficiency of command set} \index{Command set!sufficiency} First we'll look at whether it allows full control over line breaks and indentation. A detailed comparison shows that the command set used by Rose and Welsh is a subset of Knuth's command set (\fmt{indent}, \fmt{outdent}, \fmt{force}, \fmt{breakspace}, \fmt{opt}).\footnote{ The commands used by Rose and Welsh are denoted by the special symbols {\em m, o, r, i} and {\em s}. A stack is used to keep track of the indentation of the preceding lines. The symbol $m$ pushes the current horizontal print position onto the stack and the symbol $o$ pops the stack again. The metasyntax insists that every string produced from a non-terminal is bracketed by an $m$\dots$o$ pair. As no $m$ and $o$ are allowed elsewhere in a rule body, the amount of indentation is always restored to the prevoius value during formatting. The symbol $r$ denotes a line feed and a carriage return to the margin that is stored in top of the stack, whereas $i$ increments the top-of-stack margin value and then performes an $r$. The $s$ symbol is used to emphasize strings produced from a rule of the grammar. It is only allowed at the beginning of a rule body and directs the folding algorithm to force line breaks before and after the string produced from this rule. Optional line breaks (so called {\em folding options\/}, denoted `[$i$]' or `[$r$]') can be inserted between the non-terminals in the rule body. The most obvious analogy is the $i$ symbol. It corresponds to the sequence \fmt{indent}, \fmt{force} and since every indent is followed by a \fmt{force} or made superfluous by a matching \fmt{outdent} you may transform every occurence of \fmt{indent} into an optional $i$. The $r$ symbol, performed inside the $i$, denotes a \fmt{force} command. By popping the margin stack, the $o$ symbol plays the role of the \fmt{outdent} command. The two fold options `[$r$]' and `[$i$]' correspond to \fmt{break\_space} and \fmt{opt}.} Rose and Welsh in fact show by example, that any language syntax can be transformed into a formatted syntax that in itself is capable of specifying all desirable folds and changes of indentation. The main precondition for this transformation is, that the starting grammar is context free. None of the five basic commands is superfluous (as we have seen in the first part of this chapter) so we can call these basic commands the {\em necessary command set\/}. \index{Knuth, Donald E.}\index{Welsh, J.}\index{Rose, G. A.} \index{Context free grammar}\index{Necessary command set} The necessary command set enables the first point of the basic actions of a prettyprinter mentioned on page \pageref{basic-actions}. The other two points (additional local spacing of syntactic constructs; using different fonts) are things that depend on the capabilities of the typesetter and are not so much a question of the format command set. Thanks to procedural markup, as long as the prettyprinter allows us to insert strings between any two tokens at lexical level we are able to handle these two points too. However, in Rubin's rather assembler like command set \cite[p.~122]{Rubin83} we see that the necessary command set still lacks full control over vertical and horizontal spacing. One can argue over what parts of this issue belong into the domain of the typesetter and what should be left to the user's control, but there surely is an obvious need to express additional vertical separation in terms of a simple format command. In our case this is the \fmt{big\_force} command. \index{Procedural markup}\index{Markup}\index{Lexical level} \index{Rubin, Lisa F.}\index{Assembler like command set} \index{Command set!assembler like}\index{Spacing!vertical} \index{Spacing!horzontal} \index{Format commands!big force@\fmt{big\_force}} \index{big force@\fmt{big\_force}} The other command that gives better control over horizontal space is \fmt{backup}. Both \fmt{backup} and \fmt{big\_force} can be simulated by sequences of commands from the necessary command set.\footnote{The sequence `\fmt{force}, \fmt{backup}' is equal to `\fmt{outdent}, \fmt{force}, \fmt{indent}' and `\fmt{big\_force}' is something like `\fmt{force}, \fmt{null}, \fmt{force}', depending on the exact interpretation of the typesetter.} So they are not necessary but convenient short-hands. We will call them, together with the basic commands the {\em convenient command set\/}. \index{Format commands!backup@\fmt{backup}}\index{backup@\fmt{backup}} \index{Convenient command set}\index{Command set!convenient} Typesetting lines of code flushleft is not a feature commonly needed in modern structured programming languages, except in \C/\CPP\ when using preprocessor directives (and still they do not belong to the actual language itself). The \fmt{no\_indent} command caters for them but it is hardly necessary in other languages, where alone the idea of excluding single lines from the overall indentation frame violates all rules of good program layout. \index{c@\C}\index{c++@\CPP}\index{Format commands!no indent@\fmt{no\_indent}} \index{no indent@\fmt{no\_indent}} Finally the \fmt{cancel} command does not add any striking new features to the command set. It just allows more flexibility in the placement of format commands in the output. A well placed \fmt{cancel} command can obliterate a dozen rules of your prettyprinting grammar and thus can deflate prettyprinting grammars very much. So if you define sufficiency as incorporating convenience and flexibility we could call this whole set of presented commands a {\em sufficient command set}. This, however, naturally excludes the open problems mentioned in the next subsection. The two subsets of this sufficient command set are summarized in table \ref{command-set}. \index{Prettyprinting grammar!deflating}\index{Deflating prettyprinting grammars}\index{Format commands!cancel@\fmt{cancel}}\index{Sufficient command set}\index{Command set!sufficient}\index{cancel@\fmt{cancel}} \begin{figure} \begin{tabular}{rl} necessary command set $N\quad =$ & \{ \fmt{indent}, \fmt{outdent}, \fmt{force}, \fmt{break\_space}, \fmt{opt} \} \\ convenient command set $C\quad =$ & $N$ $\cup$ \{ \fmt{backup}, \fmt{big\_force} \} \\ sufficient command set $S\quad =$ & $C$ $\cup$ \{ \fmt{cancel}, \fmt{no\_indent} \} \\ \end{tabular} \caption{Naming of subsets of the command set.} \label{command-set} \end{figure} \subsection{Open Prettyprinting Problems} If you have ever tried to use a prettyprinter for your own code you will surely have come across problems concerning user control. Yehudai states, that % \index{Prettyprinting!problems}\index{User control} \index{Yehudai, A.} % \begin{quote} ``[\dots] it is not clear that any automated indentation scheme will be adequate, as I may choose different ways to lay out the same construct in different parts of my program.'' \cite[p.~85]{Yehudai80} \end{quote} % Woodman gives an example for this point that he calls ``adaptive combs'' \cite[p.~616]{Woodman86}, where a long \res{if}/\res{elsif} statement in Modula-2 is cited as: % \index{Woodman, M.}\index{adaptive combs@``adaptive combs''} \index{Modula-2} % \begin{outp} \res{if} \id{longexpression1} \res{then}\myindent\myforce \id{longstatement1}\myoutdent\myforce \res{elsif} \id{expr2} \res{then} \id{stmt2}\myforce \res{elsif} \id{longexpression3} \res{then}\myindent\myforce \id{longstatement3}\myoutdent\myforce \res{else}\myindent\myforce \id{longstatement4}\myoutdent\myforce \res{end}\myforce \end{outp} % Here the statement \id{stmt2} appears on the ``tooth'' of the comb, whereas the context rather suggests that it should appear between the teeth like all other statements. This is a question of {\em context sensitive formatting\/} and it is an open question, how to deal with this problem in terms of format commands.\footnote{ Woodman proposes the idea of ``linked folds'', i.e.~a special set of format commands that force a number of consecutive folds to be treated equally, but doesn't elaborate on it.} \index{Tooth}\index{Context sensitive formatting} \index{Linked folds} Another open problem falls into the same domain, but deals with horizontal spacing instead of line breaking. Blaschek \cite[p.~701]{Blaschek89} points out that his system is not able to align constructs horizontally, as for example in: % \index{Horizontal spacing}\index{Spacing!horizontal}\index{Blaschek, G.} % \begin{outp} \res{with} \id{stmt} $\hat{ }$ \res{do}\myindent\myforce \begin{tabular}{ll} \id{position} & \ass\ \id{pos} \\ \id{decLabel} & \ass\ \id{label} \\ \id{next} & \ass\ \res{nil} \\ \end{tabular} \myforce \res{end}\myforce \end{outp} % This is a problem that no prettyprinter to date has mastered in an automatic fashion. It is an open question whether these problems could be solved using intelligent algorithms that learn a layout style by example, like for instance the `intelligent' prettyprinter by Winter and Cook \cite{Winter89}. But maybe the worst (and oldest) prettyprinting problem is how to typeset comments! Papers as early as those of Mohilner \cite{Mohilner78} and Jackel \cite{Jackel80} address this topic and the core of the problem surely lies in the nature of comments. The paper ``Programming languages should NOT have comment statements'' by Kaelbling \cite{Kaelbling88} and that by Grogono \cite{Grogono89} strongly argue that at last comments should be treated equally as parts of the language, not as an add-on that is forgotten at first point during compilation. Grogono brings this to the point by stating that ``Comments are second class citizens.'' \cite[p.~80]{Grogono89} They are mostly allowed anywhere in the source code and prettyprinters who want to preserve them in the output have severe problems doing that without destroying the program's format, because they have to be incorporated into the prettyprinting grammar. \index{Winter, K.}\index{Cook, C.}\index{Prettyprinter!intelligent} \index{Intelligent prettyprinter}\index{Typesetting comments} \index{Comments}\index{Prettyprinting problems!worst and oldest} \index{Mohilner, Patricia R.}\index{Jackel, M.} \index{Kaelbling, M. J.}\index{Second class citizens}\index{Equality} \index{Grogono, P.}\index{Prettyprinting grammar!and comments} There have been attempts to do this in a structured way, i.e.~to divide comments into classes and to treat each class differently \cite{Richard77,Rubin83,Fritzson83,Rorbillard89}. Rose and Welsh distinguish between pre- and postcomments and state that comments must move with the syntactic elements that they refer to \cite[p.~660]{Rose81}. Kaelbling even goes as far as to demand ``scoped comments'', i.e.~comments that explicitly show to which part of the program they belong. \index{Rose, G. A.}\index{Welsh, J.}\index{Classes of comments} \index{Comments}\index{precomments@``precomments'' (Rose and Welsh)} \index{postcomments@``postcomments'' (Rose and Welsh)} \index{Kaelbling, M. J.}\index{scoped comments@``scoped comments'' (Kaelbling)} All these attempts have the same goal, but the problem of prettyprinting comments will only be solved, if they are treated as an equal part of a programming language and thus are included in the reference grammar. \section{Summary} As this has been quite a long chapter I will try to recall the main points of it now: % \index{Long chapter} In this chapter I have introduced the way of formatting that \pretzel\ uses in the generated prettyprinter. This method uses format commands that are intermixed with the text strings of the source code according to a prettyprinting grammar and interpreted by the typesetter. A few examples were given. In the second part I have tried to reconstruct the evolution of this formatting algorithm by giving a brief overview over the history of prettyprinting. This has shown the main points that structure the field (distinction between formatting policy and formatting algorithm, formalization of formatting policy through a prettyprinting grammar, different sets of format commands). From this overview I have shown how the algorithm used be the \pretzel\ system fits into the field and how sufficient its command set is. pretzel-2.0n-2/doc/project.report/chap4.tex0000644000000000000000000003043706254321707017336 0ustar rootroot% % $Id: chap4.tex,v 1.4 1995/04/20 13:17:00 gaertner Exp gaertner $ % % $Log: chap4.tex,v $ % Revision 1.4 1995/04/20 13:17:00 gaertner % Corrections proposed by JS % % Revision 1.3 1995/02/23 12:48:00 gaertner % Final revision (including figures, but without index). % % Revision 1.2 1995/02/21 09:30:00 gaertner % Changed \mkWEAVE and \preFLEX and \preBISON invocations so that % the text will compile. % % Revision 1.1 1995/02/21 09:25:16 gaertner % Initial revision % % \chapter{The Design of the System} \label{four} The idea behind the \pretzel\ program is not new. The way of using a prettyprinting grammar for formatting and the idea of generating a \WEB\ system from a formal specifiacation of the underlying programming language have been presented by Knuth and Ramsey years ago. The new thing behind the \pretzel\ program is that it combines these two ideas to produce output that is useable in a lot of different fashions. This chapter presents the evolution of the \pretzel\ program from its early design to the history of its implementation. \section{The Attribute Grammar} As said earlier, the main working mechanism of the generated prettyprinter is the use of an attribute grammar to build up prettyprinted code during a bottom-up parse of the programming language text. So one of the first steps was to look at a system that had implemented this already: Knuth's initial \WEAVE\ program and the \CWEAVE\ program that is derived from it. The first bigger aim in this project was then to build a prototype prettyprinter that implemented this notion, using Bison and the semantic actions provided in it to put together the code using a set of specially designed functions from a run time library. In fact, it was the mere design of this run time library that took up the biggest part of the time in the design stage. \index{weave@\WEAVE}\index{cweave@\CWEAVE}\index{Knuth, Donald E.} \subsection{Attributes} The basic idea that was the starting point of the design was to provide a recursive data type that implemented attributes or translations of grammar tokens and could be used during parsing. This data type was to be called {\em attribute} and should be implemented using \CPP. An attribute could be recursively defined as follows: \begin{itemize} \item A simple string is an attribute. \item A format command is an attribute. \item Any combination of two or more attributes is again an attribute. \end{itemize} This definition resulted from hand-simulating the process done by Knuth's \WEAVE\ program on the blackboard and on notepaper. It seemed at first that it would be a good idea to implement attributes as a long linked list, because the result of the prettyprinting always appeared to be a long list of strings and format commands. Whenever a grammar rule was chosen, the attributes of the tokens were simply inserted into a new list that represented the attribute of the resulting token. For efficiency reasons this idea was soon abandoned and the insertion of attributes was done by inserting references (visualized as long arrows on paper) into newly created attributes. The resulting structures looked very much like trees and the resulting output could be obtained with a simple tree traversion. An abstract way of defining attributes using the \CPP\ classes was to have one abstract base class, of which all of the three attribute types could be derived from, namely: strings, format commands and sequences of attributes. This was realized in the \id{Attribute} class. It provided three kinds of attributes, i.e.~subtypes of \id{Attribute}: \begin{enumerate} \item \id{Text\_attribute} to store simple strings. \item \id{Format\_attribute} to store format commands (implemented as an enumeration type). \item \id{Attributelist} to store a sequence of objects of type \id{Attribute} (implemented as a linked list holding attribute pointers). \end{enumerate} The recursive implementation is hidden elegantly in the definition of \id{Attributelist}, because such a list can contain any attribute, a string, a format command or simply again a list of such attributes. The final thing concerning this class was to provide a set of useful functions to handle objects of this type. This set simply consisted of two functions, namely: % \begin{enumerate} \item \id{create()} to create a \id{Text\_attribute} or a \id{Format\_attribute} from a simple string or the name of a format command. \item \id{join()} to create an \id{Attributelist} from a sequence of attributes. \end{enumerate} % Note that both functions return valid attributes and thus can be used as arguments to each other. Using attributes in this fashion therefore creates the trees that appeared earlier on paper or on the blackboard automatically in the computer's memory. \subsection{Outputting Attributes} Creating huge trees of attributes in memory would be useless unless there would be a possibility to get them out again and output them into a file or onto screen. As stated earlier this could be done by a simple tree traversion in pre-order. However, the object oriented approach that was built into the attributes now seemed to inhibit an easy way of doing this, since all of the nodes of the tree were simply of type \id{Attribute} and their initial subtype could not be retieved by simply looking at them. How do you know how to output an attribute, when you don't know if it is a string, a format command or even a list of attributes? The solution to this problem is really one of the most interesting parts of the whole program and gets to the actual core of ``real'' object oriented programming. The idea was to provide a public member function called \id{print} in each subclass of \id{Attribute} that would automatically output an object of its class in the right way, provided it was told where to put the output. This was the birth of the \id{Output} class. Objects of this class (``outputs'') can be used to output attributes. An output is attached to a \CPP\ \id{ostream} class object during creation. Any calls of the \id{print} member functions of attributes must say into which output they want to send their information. But the problem of calling the right kind of \id{print} function for every attribute is obsolete because of the built-in dynamic dispatch: every object knows its type and can therefore invoke its own specific member function. (Sending information to an output is done by taking the string or the format command out of the attribute and calling a special function \id{do\_output} of the output with this information.) The traversion is achieved by simply implementing the \id{print} function of the \id{Attributelist} as a subsequent invocation of the \id{print} functions of its members. The output to which this stream of attributes is sent then has full control over the information flow before it sends it out to the \id{ostream} object to which it is connected. In fact, an output can do much more than merely directing information flow to a specific destination: it may also be used to do any kind of processing of the attribute information, such as interpreting the format commands and translating them into typesetter understandable format; or it can do the preprocessing that is caught by the two phrases on page \pageref{two-phrases}, i.e.~reducing a sequence of \fmt{force} commands to just one or handling the behaviour of the \fmt{cancel} command. The internal structure of each output just has to wait for subsequent calls of the \id{do\_output} function and handles the incoming information as it wishes.\footnote{Unfortunately this causes the \id{Output} class to neglect the fundamental modularity of modern prettyprinters as described in chapter \ref{one}. See chapter \ref{five} (future work) for more on this topic.} Both the \id{Attribute} class and the \id{Output} class are the central and decisive part of the run time library. Attributes are used to build up the translations of tokens during parsing; Outputs are used to interpret and output these attributes to a given output stream. \section{The Structure of Pretzel} After designing and implementing the run time library for the generated prettyprinter all of the functions were tested thoroughly with a small prototype prettyprinter that could handle simple \C\ code. The main result from this time of testing was that using attributes and outputs within semantic actions of a Bison grammar to generate prettyprinted output actually worked. The next step was to think of a way of specifying a prettyprinting grammar in machine readable form that would be intuitive and similar enough to the way used by Knuth in his documentation to \WEAVE. After sketching out some rough ideas I turned to actually defining Bison grammars to parse this notation and to translate this into valid flex and Bison files. This was the birth of the formatted token and the formatted grammar files and the functions that transform them into valid flex and Bison code. The general idea of these functions is to transform a sequence like % \begin{verbatim} "begin" BEG {"\\&{begin}"} \end{verbatim} % into a line of flex like % \begin{verbatim} "begin" {*rvalue=create("\\&{begin}"); return(BEG);} \end{verbatim} % where \verb+*rvalue+ stores the semantic value of the token and is of type \id{Attribute}$\ast$. A declaration in the formatted grammar file like % \begin{verbatim} block : BEG stmt_list END {$1 + $2 + force + $3} ; \end{verbatim} % should be transformed into lines of Bison input as in: % \begin{verbatim} block : BEG stmt_list END {$$=join($1,$2,create(force),$3);} ; \end{verbatim} % It is again an astonishing point to see the universality of the \id{Attribute} class. Designed for building up attributes during parsing within the prettyprinter, they suddenly were used to generate the code put into the flex and Bison files. The result of all this coding were two generators (see also figure \ref{generator-funs}): \begin{itemize} \item A \id{build\_pscan} function that reads a formatted token file from an \id{istream} class object, parses and translates the contents of the file and writes to an \id{ostream} class object the generated code of a prettyprinting scanner. This scanner acts in the way that was specified in the input. \item A \id{build\_pparse} function that reads a formatted grammar file from an \id{istream} and writes a Bison source for a prettyprinting parser to an \id{ostream}. This parser acts in the way specified in the input. \end{itemize} \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/generator-funs.latex} \end{center} \caption{The two generator functions within \pretzel.} \label{generator-funs} \end{figure} The translated code not only consists of the pure flex and Bison definitions for the prettyprinting grammar, but also contains the code for the actual prettyprinting functions, that were the major goal of this project. These two functions do the main work of \pretzel. The last step of this project was then to write the actual \pretzel\ program. It simply does nothing else but to form a nice user interface to the two parser functions. See figure \ref{module-depends} for an overview over the dependency structure of the modules involved in \pretzel. \begin{figure}[htb] \begin{center} \leavevmode \input{../figures/module-depends.latex} \end{center} \caption{The dependency structure of the modules of \pretzel.} \label{module-depends} \end{figure} \section{History} The design phase began very much in the beginning of 1993 with an analysis of the sourcecode of Knuth's \PASCAL\ \WEAVE\ program. In May 1993 I had designed a prototype prettyprinter for simple \C\ code that simulated very much the kind of prettyprinter that \pretzel\ should generate. After testing and playing around with it, the second and last step could begin. In June 1993 I thought of a way to specify a prettyprinting grammar that would be easy to read and easy to parse. At this point the prettyprinting scanners and parsers emerged. As mentioned earlier they themselves were written in flex and Bison and use the \id{Attribute} class during code generation. Finally I had only to write a main program that would invoke these two parsers and write the generated code into files. I began coding this program in July 1993 and called it \pretzel. The final revisions are documented in the \t{diary} file that is part of the \pretzel\ distribution. pretzel-2.0n-2/doc/styles/0000755000000000000000000000000006474562302014153 5ustar rootrootpretzel-2.0n-2/doc/styles/moreverb.sty0000644000000000000000000001526606240156271016542 0ustar rootroot%%% moreverb.sty %%% AJCD 20 Sep 91 %%% adds various verbatim environments using Rainer Sch\"opf's new verbatim %%% environment. %%% load verbatim style if not already loaded. \@ifundefined{verbatim@processline}{\input verbatim.sty}{} %%% verbatimwrite writes all text in its body to a file, the name of which it %%% is given as an argument. Written by RmS. \newwrite \verbatim@out \def\verbatimwrite#1{% \@bsphack \immediate\openout \verbatim@out #1 \let\do\@makeother\dospecials \catcode`\^^M\active \catcode`\^^I=12 \def\verbatim@processline{% \immediate\write\verbatim@out {\the\verbatim@line}}% \verbatim@start} \def\endverbatimwrite{% \immediate\closeout\verbatim@out \@esphack} %%% Auxiliary macros and counters for expanding tabs. Use by listing and %%% verbatimtab environments. \newcount\tab@position \newcount\tab@size \newcount\verbatimtabsize \verbatimtabsize=8 \def\@xobeytab{\leavevmode\penalty\@M {\loop\ \global\advance\tab@position-1 \ifnum\tab@position>0 \repeat}} \begingroup \catcode`\^^I=\active \gdef\@vobeytabs{\catcode`\^^I\active\let^^I\@xobeytab}% \endgroup \def\verbatim@tabexpand#1{% \ifx#1\@nil \let\next\par \else \ifx#1\@xobeysp \@xobeysp\advance\tab@position-1 \else \ifx#1\@xobeytab \@xobeytab\else #1\advance\tab@position-1 \fi\fi \ifnum\tab@position=0 \tab@position\tab@size \fi \let\next\verbatim@tabexpand \fi\next } %%% listing defines a verbatim environment with numbered lines; it takes an %%% optional argument specifying the number of lines between numbered %%% lines, and a mandatory argument specifying the starting line. listingcont %%% continues from the place where listing left off. %%% The style in which the label is set can be altered by re-defining %%% \listinglabel. * versions are provided. \newcount\listing@line \listing@line=1 \newcount\listing@step \listing@step=1 % Adding an \hbox in front of the line causes a line break, so I go % through this rigmarole to get the lines aligned nicely. I probably % missed some obvious reason why \hboxes don't work. \def\listinglabel#1{\rlap{\small\rm\the#1}\hskip2.5em} \def\thelisting@line{% \setbox0\hbox{\listinglabel\listing@line}% \@tempcnta=\listing@line \divide\@tempcnta\listing@step \multiply\@tempcnta\listing@step \ifnum\listing@line=1 \unhbox0 \else \ifnum\@tempcnta=\listing@line \unhbox0 \else \hskip\wd0 \fi\fi} \def\listing{\@ifnextchar[{\@listing}{\@listing[1]}} \def\@listing[#1]#2{% \global\listing@line=#2\global\listing@step=#1\listingcont} \def\listingcont{% \tab@size=\verbatimtabsize \def\verbatim@processline{\tab@position\tab@size \thelisting@line \global\advance\listing@line1 \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start} \let\endlisting=\endtrivlist \let\endlistingcont=\endtrivlist \@namedef{listing*}{\@ifnextchar[{\@listingstar}{\@listingstar[1]}} \def\@listingstar[#1]#2{% \global\listing@line=#2\global\listing@step=#1\relax \csname listingcont*\endcsname} \@namedef{listingcont*}{% \def\verbatim@processline{% \thelisting@line \global\advance\listing@line1 \the\verbatim@line\par}% \@verbatim\verbatim@start} \expandafter\let\csname endlisting*\endcsname =\endtrivlist \expandafter\let\csname endlistingcont*\endcsname =\endtrivlist %%% file input version of listing \def\listinginput{% \@ifnextchar[{\@listinginput}{\@listinginput[1]}} {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N \lowercase{% \gdef\@listinginput[#1]#2#3{\begingroup \global\listing@line=#2\global\listing@step=#1 \tab@size=\verbatimtabsize \def\verbatim@processline{\tab@position\tab@size \thelisting@line \global\advance\listing@line1 \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs \def\verbatim@addtoline##1~{% \verbatim@line\expandafter{\the\verbatim@line##1}}% \openin\verbtab@in=#3 \ifeof\verbtab@in\typeout{No file #3.}\else \verbtab@oktrue \loop \read\verbtab@in to \verbtab@line \ifeof\verbtab@in\verbtab@okfalse\else \expandafter\verbatim@addtoline\verbtab@line \verbatim@processline \verbatim@startline \fi \ifverbtab@ok\repeat \closein\verbtab@in\fi \endtrivlist\endgroup\@doendpe}}} %%% verbatimcmd is a verbatim environment with the exception of the escape and %%% grouping characters \, {, }. \def\verbatimcmd{% \@verbatim \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \frenchspacing\@vobeyspaces\verbatim@start } \def\endverbatimcmd{% \let\par\relax \def\verbatim@{\endtrivlist\endgroup}% \begingroup} %%% boxedverbatim produces a verbatim environment in a framed box. %%% written by Victor Eijkhout \def\boxedverbatim{% % redefine `processline' to produce only a line as wide % as the natural width of the line \def\verbatim@processline{% {\setbox0=\hbox{\the\verbatim@line}% \hsize=\wd0 \the\verbatim@line\par}}% % save the verbatim code in a box \setbox0=\vbox\bgroup \verbatim } \def\endboxedverbatim{% \endverbatim \egroup % close the box and `fbox' it \fbox{\box0}% <<<=== change here for centering,... } %%% verbatimtab is a verbatim environment which expands tab characters; it %%% takes an optional argument specifying the width of tab stops \def\verbatimtab{\futurelet\next\@verbatimtab} \def\@verbatimtab{\if\next[ \let\next\@@verbatimtab\else \def\next{\@@verbatimtab[\the\verbatimtabsize]}\fi\next} \def\@@verbatimtab[#1]{% \do@verbatimtab{#1}{% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs\verbatim@start}% } \def\do@verbatimtab#1#2{% \tab@size=#1 \def\verbatim@processline{\tab@position\tab@size \expandafter\verbatim@tabexpand\the\verbatim@line\@nil}#2 } \let\endverbatimtab=\endtrivlist %%% file input version of verbatimtab \newread\verbtab@in \newif\ifverbtab@ok \def\verbatimtabinput{% \@ifnextchar[{\@verbatimtabinput}{\@verbatimtabinput[\the\verbatimtabsize]}} {\catcode`\~=\active \lccode`\~=`\^^M \lccode`\N=`\N \lowercase{% \gdef\@verbatimtabinput[#1]#2{\begingroup \do@verbatimtab{#1}{% \@verbatim\frenchspacing\@vobeyspaces\@vobeytabs}% \def\verbatim@addtoline##1~{% \verbatim@line\expandafter{\the\verbatim@line##1}}% \openin\verbtab@in=#2 \ifeof\verbtab@in\typeout{No file #2.}\else \verbtab@oktrue \loop \read\verbtab@in to \verbtab@line \ifeof\verbtab@in\verbtab@okfalse\else \expandafter\verbatim@addtoline\verbtab@line \verbatim@processline \verbatim@startline \fi \ifverbtab@ok\repeat \closein\verbtab@in\fi \endtrivlist\endgroup\@doendpe}}} pretzel-2.0n-2/doc/styles/pretzeldoc.sty0000644000000000000000000000532406360665140017071 0ustar rootroot% $Id: pretzeldoc.sty,v 1.2 1997/07/09 10:39:11 gaertner Exp $ % % Package containing global macros for the documentation of the % pretzel project (both source code and user documentation). % identification: \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{pretzeldoc}[1996/03/07] % % initial code: % % declaration of options: % % execution of options: % % package loading: \RequirePackage{a4} \RequirePackage{makeidx} %\RequirePackage{showidx} % bites in Pretzelbook \RequirePackage{moreverb} \RequirePackage{multicol} \RequirePackage{pretzel-latex} % % main code: % % some logos % \def\WEB{{\tt WEB}} \def\CWEB{{\tt CWEB}} \def\TANGLE{{\tt TANGLE}} \def\WEAVE{{\tt WEAVE}} \def\pretzel{{Pretzel}} \newcommand{\noweb}{{\tt noweb}} \newcommand{\HTML}{{\sc HTML}} \def\CTANGLE{{\tt CTANGLE}} \def\CWEAVE{{\tt CWEAVE}} \def\C{{\sc C}} \def\CPP{{\C\raise1pt\hbox{++}}} \def\ALGOL{{\sc Algol}} \def\LISP{{\sc Lisp}} \def\PASCAL{{\sc Pascal}} \def\UNIX{{\sc UNIX}} \def\t#1{{\tt #1}} % short form for typewriter style % macros for formatting the examples \newenvironment{inp}{% % input of an example \flushleft % examples are flushed left \leftskip 1em % but indented a bit \catcode`\_=12 % typeset underlines \tt % use typewriter type }{% \endflushleft } \newcount\ind % counter for counting amount of indentation \newenvironment{outp}{% % output of prettyprinted text \flushleft \leftskip 1em \sfcode`;=3000 % a `;' acts like a period \pretolerance=10000 % no second pass for paragraph makeup \hyphenpenalty 10000 \exhyphenpenalty 10000 % no hypenation \global\ind=0 % reset indentation \hangindent=\ind em % standard left indentation for rest of para \hangafter=0 % align all lines \parindent=0pt % no extra para indentation \noindent\kern \ind em % get into horizontal mode \ignorespaces }{% \endflushleft } \def\id#1{\mbox{\it#1\/}} % identifiers in italics \def\fmt#1{\mbox{\it #1\/}} % format commands also \def\res#1{\mbox{\bf #1}} % reserved words in boldface \def\ass{\mbox{${}\mathrel{:=}{}$}} % assignment operator %\def\andsign{\mbox{$\wedge$}} % and sign \def\andsign{\res{and}} \def\myindent{\advance\ind by1} % indent \def\myoutdent{\advance\ind by-1} % outdent \def\myforce{\par\noindent\kern\ind em} % forced line break \def\mybackup{\hspace{-1em}} % backup one em % % $Log: pretzeldoc.sty,v $ % Revision 1.2 1997/07/09 10:39:11 gaertner % use \def instead of \newcommand for pretzel logo in case % it's already defined. % % Revision 1.1 1996/03/07 17:28:09 gaertner % Initial revision % % % pretzel-2.0n-2/doc/styles/index.list0000644000000000000000000000110606360650267016157 0ustar rootrootindex.html & LaTeX styles for Pretzel Makefile & The Makefile moreverb.sty & non-standard style (by AJCD 20 Sep 91) used by pretzeldoc.sty pretzel-latex.sty & LaTeX style for typesetting plain Pretzel prettyprinted code pretzel-noweb-style.nw & noweb source of the pretzel-noweb.sty, the LaTeX style for typesetting noweb documents that use a Pretzel prettyprinting filter pretzel-noweb.sty & generated from pretzel-noweb-style.nw pretzel.sty & Old style for use with project report pretzeldoc.sty & New style used for the project documentation (both source code and documentation) pretzel-2.0n-2/doc/styles/pretzel-noweb-style.nw0000644000000000000000000001570106474562302020460 0ustar rootroot% $Id: pretzel-noweb-style.nw,v 1.3 1998/02/24 15:18:13 gaertner Exp $ %---------------------------------------------------------------------- % % XXX % % [noweb] % (history at end) \documentclass{article} % %\usepackage{german} \usepackage{rcs} \usepackage{noweb} %\usepackage{pretzel-noweb} % don't use myself % \begin{document} \title{{\tt pretzel-noweb.sty} \\ Interfacing Pretzel and {\tt noweb} in \LaTeX} \author{Felix G\"artner} \RCSdate $Date: 1998/02/24 15:18:13 $ \maketitle \section{Introduction} This file contains some \TeX{} and \LaTeX{} macros that support prettyprinting in Norman Ramsey's {\tt noweb}. It provides definitions for the macros that a Pretzel prettyprinting filter for \LaTeX{} emits. The definitions in this file are based on the information in the {\tt support.nw} file from the {\tt noweb} distribution that explains the macros used in {\tt noweb}. Also, a similar file from Lee Wittenberg that belong to his Pretzel prettyprinter for Java has been very helpful. \section{What Pretzel needs} The macros that are output by the [[Latex_cweb_output]] class are basicly the following: <>= \pretzelindent \pretzeloutdent \pretzelopt#1 % opt with #1 times 10 penalty \pretzelbackup \pretzelbreakspace \pretzelforce#1 % parm below is to eat {} generated by Pretzel \pretzelbigforce \pretzelnoindent @ The interface between the {\tt noweb} prettyprinting filter and the {\tt noweb} intermediate stream representation emits [[\begin{ppcode}]] and [[\end{ppcode}]] lines around the prettyprinted text. This is usefull to define specialities of the code environment. Also one macro from the \texttt{noweb.sty} is redefined to make \texttt{CWEB} like prettyprinting possible. In situations where prettyprinting is not wished or where the prettyprinter simply failed to do his task well, we want to try and restore the old \texttt{noweb}-style verbatim environment by issuing the [[\pretzelnwcodeimitation]] macro before outputting the code. \section{The Code} This is an overview over the file. <<*>>= % pretzel-noweb.sty -- interfacing Pretzel and noweb in LateX % (c) 1997 by Felix Gaertner. Look at pretzel-noweb-style.nw if % you want to make changes. % <> <> <> <> <> <> <> @ I don't know if it's a good idea to include the {\tt noweb} style here or leave this to the user. I'll leave it for now and will think about it later. <>= %\input noweb.sty @ In any case, we'll need to redefine the [[\@begincode]] macro of {\tt noweb}. The {\tt noweave} processor will bracket code parts with [[\nwbegincode]] and [[\nwendcode]]. The [[\nwbegincode]] macro sets separations and penalties and then calls [[\@begincode]], which captures the common setup code also used in the [[webcode]] environment that the style offers. Within [[\@begincode]] the [[verbatim]] kind of code environment ist setup and we have to alter this, since the Pretzel macros do all of the work by themselves. This redefinition of [[\@begincode]] bases on Lee Wittenberg's implementation. It differs from the original version in three things: \begin{itemize} \item It doesn't setup [[\obeylines]] and so leaves line breaks to \TeX{} and the format commands introduced by Pretzel. \item It doesn't call [[\setupcode]] and so preserves the usual category codes of characters like {\tt\$} and {\tt\_}. We have to make sure that the Pretzel prettyprinter handles them well ourself (which is especially tricky in identifiers, see below). \item The last line states [[\let\eatline=\relax]]. I don't know why. \end{itemize} <>= \def\@begincode{% \trivlist \item[]% \leftskip\@totalleftmargin \advance\leftskip\codemargin \rightskip\hsize \advance\rightskip -\codehsize \parskip\z@ \parindent\z@ \parfillskip\@flushglue \linewidth\codehsize \nowebsize \let\maybehbox\mbox % \let\eatline=\relax } @ Sometimes we would like to have the ``real'' version of [[\@begincode]] still available because prettyprinting is not wished or cannot be done. The [[\pretzelnwcodeimitation]] macro can be issued in such cases. It contains all the \TeX{} code that was left away in the above redefinition and thus turns everything into a state as if nothing has been changed. <>= \def\pretzelnwcodeimitation{ \@@par \def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}% \obeylines \@noligs \ifx\verbatim@nolig@list\undefined\else \let\do=\nw@makeother \verbatim@nolig@list \do@noligs\` \fi \setupcode \frenchspacing \@vobeyspaces } @ A new counter keeps track of the indentation. <>= \newcount\ind @ <>= \newenvironment{ppcode}{% \sfcode`;=3000 % a `;' acts like a period \pretolerance=10000 % \hyphenpenalty=10000 % \exhyphenpenalty=10000 % \global\ind=2 % This fakeout is important for opt to work correctly \par \global\hangindent\ind em }{% % \mathout } @ Finally here are the actual formatting macros. They go back to the original Knuthian versions as in {\tt cwebmac.sty}. <>= \newbox\bak\setbox\bak=\hbox to -1em{} % backspace 1 em \newbox\bakk\setbox\bakk=\hbox to -2em{} % backspace 2 ems \def\pretzelindent{\global\advance\ind by1\hangindent\ind em}% \def\pretzeloutdent{\global\advance\ind by-1}% \def\pretzelopt#1{\hfil\penalty#10\hfilneg}% \def\pretzelbackup{\copy\bak}% \def\pretzelbreakspace{\hfil\penalty-1\hfilneg \kern2.5em\copy\bakk\ignorespaces}% % parm below is to eat {} generated by Pretzel \def\pretzelforce#1{\mathout\par\hangindent\ind em\noindent \kern\ind em\copy\bakk#1\ignorespaces}% \def\pretzelbigforce{\mathout\par\smallskip\pretzelforce}% \def\pretzelnoindent{\hskip-\ind em\hskip 2em}% @ We'll change the category code of [[^^K]] (which is what?) so that be can bracket strings with it using [[\verb*]]. I'll better use the explicit value 12 instead of [[\other]], because it sometimes messes up \LaTeX. <>= \catcode`\^^K=12 % 12=other, for \verb* with strings @ We'll also have a macro that handles underscores in identifiers correctly. <>= \def\pretzelid#1{\begingroup\catcode`\_=12% #1\endgroup} @ These two macros allow better handling of math mode switching. Thanks to Lee Wittenberg for the idea. <>= \def\mathin{\ifmmode\else\begin{math}\fi{}} \def\mathout{\ifmmode\end{math}\fi{}} @ \end{document} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% $Log: pretzel-noweb-style.nw,v $ Revision 1.3 1998/02/24 15:18:13 gaertner Added macro to fake original noweb output. Revision 1.2 1998/02/23 12:52:11 gaertner Cleaned up documentation. Revision 1.1 1997/07/09 08:35:09 gaertner Initial revision pretzel-2.0n-2/doc/styles/index.html0000644000000000000000000000272006360650344016147 0ustar rootroot Index file for directory "pretzel/doc/styles" of Pretzel distribution

Index file for directory "pretzel/doc/styles" of Pretzel distribution

Files and directories are:

index.html

    LaTeX styles for Pretzel
Makefile
    The Makefile
moreverb.sty
    non-standard style (by AJCD 20 Sep 91) used by pretzeldoc.sty
pretzel-latex.sty
    LaTeX style for typesetting plain Pretzel prettyprinted code
pretzel-noweb-style.nw
    noweb source of the pretzel-noweb.sty, the LaTeX style for typesetting noweb documents that use a Pretzel prettyprinting filter
pretzel-noweb.sty
    generated from pretzel-noweb-style.nw
pretzel.sty
    Old style for use with project report
pretzeldoc.sty
    New style used for the project documentation (both source code and documentation)

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 10:50:44 MESZ 1997 pretzel-2.0n-2/doc/styles/pretzel-noweb-style.dvi0000644000000000000000000001673006474270015020616 0ustar rootroot÷ƒ’À;è TeX output 1998.02.23:1348‹ÿÿÿÿ y ý£ ? þ’žëó߆µTG® cmtt12»pretzel-noweb.styŽŸ‘b`÷óDÓítG®G®cmr17ºInŒqterfacing–7tPretzel“and“»noweb“ºin“LŸüdú‘úKGóX«Q cmr12¼AŽŽ‘¹”ºT‘ý[™Ÿ¸-EŽ‘;gXŽŸ’Çò ¼F‘ÿVelix‘ê¨G‘ú artnerŽŽŽŽŽŸˆ‹’Ë?èJuly–ê¨9,“1997ŽŸ+Ä‘>óÂÖN ff cmbx12È1Ž‘VLËInŒÌtros3ductionŽ©ç‘>óKñ`y cmr10²This–×û le“con¸ãtains“some“T‘þU>Ÿ'EŽ›ãxX“and“LŸýó5‘üffóÙ“ Rcmr7±AŽŽ‘͉²T‘þU>Ÿ'EŽ˜X“macros“that“suppGort“prett•¸ãyprin“ting‘×ûinޤ ‘>Norman–†ŽRamsey's“óßêprett•¸ãyprin“ting–UU lter“for“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX“emits.Ž¡‘MThe–‹Úde nitions“in“this“ le“are“based“on“the“information“in“the“¹support.nwŽ¡‘>² le–…from“the“¹noweb“²distribution“that“explains“the“macros“used“in“¹noweb².‘öXAlso,Ž¡‘>a–ĺsimilar“ le“from“Lee“Witten¸ãbšGerg“that“b˜elong“to“his“Pretzel“prett•¸ãyprin“ter‘ĺforŽ¡‘>Jaš¸ãv‘ÿqÇa–UUhas“bGeen“v˜ery“helpful.ŽŸ!Ä‘>È2Ž‘VLËWhat–ffPretzel“needsަ‘>²The–)macros“that“are“output“b¸ãy“the“¹Latex_cweb_output“²class“are“basicly“theŽ¡‘>follo¸ãwing:ŽŸ‘$˜ó|{Ycmr8Á1Ž‘>ó !",š cmsy10¸hóý': cmti10Êmacr›ÿ}'os–“çoutput“by“Pr˜etzel“Á1¸iŽ’¹×üŽ¡‘H¹\pretzelindentŽ¡‘H\pretzeloutdentŽ¡‘H\pretzelopt#1‘SÿÐ%–?ýopt“with“#1“times“10“penaltyŽ¡‘H\pretzelbackupŽ¡‘H\pretzelbreakspaceŽ¡‘H\pretzelforce#1‘IÖ%–?ýparm“below“is“to“eat“{}“generated“by“PretzelŽ¡‘H\pretzelbigforceŽ¡‘H\pretzelnoindentŽŽŸ’è²1ŽŽŒ‹* y ý£ ? ýä‘M²The–ÑÇinš¸ãterface“bGet˜w˜een“the“¹noweb“²prett˜yprin˜ting“ lter“and“the“¹noweb“²in˜ter-ޤ ‘>mediate–Zqstream“represen¸ãtation“emits“¹\begin{ppcode}“²and“¹\end{ppcode}“²linesŽ¡‘>around–•Ôthe“prett•¸ãyprin“ted–•Ôtext.‘3EThis“is“usefull“to“de ne“spšGecialities“of“the“co˜deŽ¡‘>en•¸ãvironmen“t.ŽŸ!Ä‘>È3Ž‘VLËThe‘ffCos3deŽŸç‘>²This–UUis“an“o•¸ãv“erview›UUo“v“er˜the˜ le.Ž©‘Ñ”Á2aŽ‘>¸hÊ*‘“çÁ2a¸iŽ‘V÷}Ž¡‘H¹%–?ýpretzel-noweb.sty‘ ú--“interfacing“Pretzel“and“noweb“in“LateXŽ¡‘H%–?ý(c)“1997“by“Felix“Gaertner.“Look“at“pretzel-noweb-style.nw“ifŽ¡‘H%–?ýyou“want“to“make“changes.Ž¡‘H%Ž¡‘H¸hÊinclude–“çother“styles“Á2b¸iŽŽ¡‘HhÊr–ÿ}'e“de ne–“ç¹noweb“Êmacr‘ÿ}'os“Á3a¸iŽŽ¡‘HhÊc‘ÿ}'ounting–“çindentation“Á3b¸iŽŽ¡‘HhÊthe–“ç¹ppcode“Êenvir‘ÿ}'onment“Á3c¸iŽŽ¡‘HhÊthe–“çformatting“macr‘ÿ}'os“Á4a¸iŽŽ¡‘HhÊsp–ÿ}'e“cials‘“çÁ4b¸iŽŽ¦‘M²I‘Kdon't–Kknoš¸ãw“if“it's“a“go•Go“d–Kidea“to“include“the“¹noweb“²st˜yle“here“or“lea˜v˜e“thisŽ¡‘>to–UUthe“user.‘qÇI'll“lea•¸ãv“e–UUit“for“no¸ãw“and“will“think“abGout“it“later.ަ‘X°Á2bŽ‘>¸hÊinclude–“çother“styles“Á2b¸iŽ’¦FýŽ¡‘H¹%\input‘?ýnoweb.styŽŽŸ’è²2ŽŽŒ‹ y ý£ ? ýä‘M²In–ì anš¸ãy“case,‘¹w˜e'll“need“to“rede ne“the“¹\@begincode“²macro“of“¹noweb².‘5ëTheޤ ‘>¹noweave–¶Œ²prošGcessor“will“brac•¸ãk“et–¶Œco˜de“parts“with“¹\nwbegincode“²and“¹\nwendcode².Ž¡‘>The–8ã¹\nwbegincode“²macro“sets“separations“and“pGenalties“and“then“calls“¹\@begincode²,Ž¡‘>whicš¸ãh– ÷captures“the“common“setup“coGde“also“used“in“the“¹webcode“²en˜vironmen˜tŽ¡‘>that–}Fthe“stš¸ãyle“o ers.‘é™Within“¹\@begincode“²the“¹verbatim“²kind“of“coGde“en˜viron-Ž¡‘>menš¸ãt–g´ist“setup“and“w˜e“ha˜v˜e“to“alter“this,‘lLsince“the“Pretzel“macros“do“all“of“theŽ¡‘>w•¸ãork›UUb“y˜themselv“es.Ž¡‘MThis–jªrede nition“of“¹\@begincode“²bases“on“Lee“Wittenš¸ãbGerg's“implemen˜tation.Ž¡‘>It–UUdi ers“from“the“original“v¸ãersion“in“three“things:ŽŸ.Œ‘M¸ŽŽŽ‘W²It–wdoGesn't“setup“¹\obeylines“²and“so“lea•¸ãv“es–wline“breaks“to“T‘þU>Ÿ'EŽ‘ãxX“and“theŽ¡‘Wformat–UUcommands“inš¸ãtroGduced“b˜y“Pretzel.Ž©EÒ‘M¸ŽŽŽ‘W²It–ó·došGesn't“call“¹\setupcode“²and“so“preserv¸ães“the“usual“category“co˜des“ofŽ¡‘Wc•¸ãharacters›¾lik“e˜¹$˜²and‘_T‰ff&fŽ‘…º.‘«õW‘ÿ*ªe˜ha“v“e˜to˜mak“e˜sure˜that˜the˜Pretzel˜pret-Ž¡‘Wt•¸ãyprin“ter–ghandles“them“wš¸ãell“ourself“(whic˜h“is“espGecially“tric˜ky“in“iden˜ti ers,Ž¡‘Wsee‘UUbGelo¸ãw).ަ‘M¸ŽŽŽ‘W²The–UUlast“line“states“¹\let\eatline=\relax².‘qÇI“don't“knoš¸ãw“wh˜y‘ÿ*ª.ŽŸ.Œ‘Ñ”Á3aŽ‘>¸hÊr–ÿ}'e“de ne–“ç¹noweb“Êmacr‘ÿ}'os“Á3a¸iŽ’³g§Ž¡‘H¹\def\@begincode{%Ž¡‘qÿè\trivlist‘?ý\item[]%Ž¡‘qÿè\leftskip\@totalleftmargin‘?ý\advance\leftskip\codemarginŽ¡‘qÿè\rightskip\hsize–?ý\advance\rightskip“-\codehsizeŽ¡‘qÿè\parskip\z@–?ý\parindent\z@“\parfillskip\@flushglueŽ¡‘qÿè\linewidth\codehsizeŽ¡‘qÿè\nowebsizeŽ¡‘qÿè\let\maybehbox\mboxŽ¡‘H%‘$¿ë\let\eatline=\relaxŽ¡‘H}ޤEÑ‘M²A–UUnew“counš¸ãter“k˜eeps“trac˜k“of“the“inden˜tation.Ž¡‘X°Á3bŽ‘>¸hÊc‘ÿ}'ounting–“çindentation“Á3b¸iŽ’¬Hiޤ ‘H¹\newcount\indŽŸ‹¢‘ JxÁ3cŽ‘>¸hÊthe–“ç¹ppcode“Êenvir‘ÿ}'onment“Á3c¸iŽ’»Ž¡‘H¹\newenvironment{ppcode}{%Ž¡‘qÿè\sfcode`;=3000‘SÿÐ%–?ýa“`;'“acts“like“a“periodŽ¡‘qÿè\pretolerance=10000‘?ý%Ž¡‘qÿè\hyphenpenalty=10000‘?ý%Ž¡‘qÿè\exhyphenpenalty=10000‘?ý%Ž¡‘qÿè\global\ind=2–?ý%“This“fakeout“is“important“for“opt“to“work“correctlyŽ¡‘qÿè\parŽ¡‘qÿè\global\hangindent\ind‘?ýemŽ¡‘H}{%Ž¡‘H%‘)ÿè\mathoutŽ¡‘H}ŽŽŸ’è²3ŽŽŒ‹ Ž y ý£ ? ýä‘M²Finally–($here“are“the“actual“formatting“macros.‘b·They“go“bac¸ãk“to“the“originalޤ ‘>Kn•¸ãuthian›UUv“ersions˜as˜in˜¹cwebmac.sty².Ž©‘Ñ”Á4aŽ‘>¸hÊthe–“çformatting“macr‘ÿ}'os“Á4a¸iŽ’²tzŽ¡‘H¹\newbox\bak\setbox\bak=\hbox–?ýto“-1em{}“%“backspace“1“emŽ¡‘H\newbox\bakk\setbox\bakk=\hbox–?ýto“-2em{}“%“backspace“2“emsŽ¡¡‘H\def\pretzelindent{\global\advance\ind–?ýby1\hangindent\ind“em}%Ž¡‘H\def\pretzeloutdent{\global\advance\ind‘?ýby-1}%Ž¡‘H\def\pretzelopt#1{\hfil\penalty#10\hfilneg}%Ž¡‘H\def\pretzelbackup{\copy\bak}%Ž¡‘H\def\pretzelbreakspace{\hfil\penalty-1\hfilnegŽ¡‘qÿè\kern2.5em\copy\bakk\ignorespaces}%Ž¡‘H%–?ýparm“below“is“to“eat“{}“generated“by“PretzelŽ¡‘H\def\pretzelforce#1{\mathout\par\hangindent\ind‘?ýem\noindentŽ¡‘qÿè\kern\ind‘?ýem\copy\bakk#1\ignorespaces}%Ž¡‘H\def\pretzelbigforce{\mathout\par\smallskip\pretzelforce}%Ž¡‘H\def\pretzelnoindent{\hskip-\ind–?ýem\hskip“2em}%ަ‘M²W‘ÿ*ªe'll–³7cš¸ãhange“the“category“coGde“of“¹^^K‘²Ý²(whic˜h“is“what?)‘‹nso“that“bGe“canŽ¡‘>brac•¸ãk“et–ã¾strings“with“it“using“¹\verb*².‘KêI'll“bGetter“use“the“explicit“v‘ÿqÇalue“12“insteadŽ¡‘>of–UU¹\other²,“bGecause“it“sometimes“messes“up“LŸýó5‘üff±AŽŽ‘͉²T‘þU>Ÿ'EŽ‘ãxX.ަ‘X°Á4bŽ‘>¸hÊsp–ÿ}'e“cials‘“çÁ4b¸iŽ‘r‡Ž¡‘H¹\catcode`\^^K=12‘ÿô%–?ý12=other,“for“\verb*“with“stringsަ‘M²W›ÿ*ªe'll–UUalso“ha•¸ãv“e–UUa“macro“that“handles“underscores“in“iden¸ãti ers“correctly˜.ަ‘ JxÁ4cŽ‘>¸hÊsp–ÿ}'e“cials‘“çÁ4b¸iŽ‘r‡²+Ž‘zN3¸ŽŽ¡‘H¹\def\pretzelid#1{\begingroup\catcode`\_=12%Ž¡‘Rú#1\endgroup}ަ‘M²These›Ýžt•¸ãw“o˜macros˜allo“w˜b•Getter˜handling˜of˜math˜mo“de˜switc¸ãhing.‘ ¡ThanksŽ¡‘>to–UULee“Witten¸ãbGerg“for“the“idea.ަ‘X°Á4dŽ‘>¸hÊsp–ÿ}'e“cials‘“çÁ4b¸iŽ‘r‡²+Ž‘zN3¸ŽŽ¡‘H¹\def\mathin{\ifmmode\else\begin{math}\fi{}}Ž¡‘H\def\mathout{\ifmmode\end{math}\fi{}}ŽŽŸ’è²4ŽŽŒø!ƒ’À;èy—óý': cmti10óÂÖN ff cmbx12ó|{Ycmr8óX«Q cmr12ó߆µTG® cmtt12óDÓítG®G®cmr17óßê pretzel-noweb.sty pretzel-noweb-style.dvi: pretzel-noweb-style.nw noweave -delay -index pretzel-noweb-style.nw > pretzel-noweb-style.tex latex pretzel-noweb-style.tex latex pretzel-noweb-style.tex clean: rm *.aux *.log *.tex clobber: clean rm *.dvi release: $(STYLES) $(MORESTYLES) $(OTHERSTYLES) cp $(STYLES) $(MORESTYLES) $(OTHERSTYLES) $(TEXINPUTSDIR) pretzel-2.0n-2/doc/styles/pretzel-latex.sty0000644000000000000000000000357706360664674017541 0ustar rootroot% $Id: pretzel-latex.sty,v 1.4 1997/07/09 10:36:25 gaertner Exp $ % % formatting macros for Latex_cweb_output class % make the Logo available :-) (use \def in case it's already defined) \def\pretzel{{Pretzel}} \newcount\ind % counter for counting amount of indentation \newenvironment{ppcode}{% % output of prettyprinted text \catcode`\^^M=5 % take care that any \obeylines is ignored \flushleft \leftskip 1em \sfcode`;=3000 % a `;' acts like a period \pretolerance=10000 % no second pass for paragraph makeup \hyphenpenalty 10000 \exhyphenpenalty 10000 % no hypenation \global\ind=0 % reset indentation \hangindent=\ind em % standard left indentation for rest of para \hangafter=0 % align all lines \parindent=0pt % no extra para indentation \noindent\kern \ind em % get into horizontal mode \ignorespaces }{% \endflushleft } \def\pretzelindent{\advance\ind by1} % indent \def\pretzeloutdent{\advance\ind by-1} % outdent \def\pretzelopt#1{\hfil\penalty#10\hfilneg} % optional line break \def\pretzelbackup{\hspace{-1em}} % backup one em \def\pretzelbreakspace{\hfil\penalty-1\hfilneg\kern2.5em\ignorespaces} % breakspace \def\pretzelforce{\par\noindent\kern\ind em} % forced line break \def\pretzelbigforce{\pretzelforce\smallskip} % bigforce \def\pretzelnoindent{\hskip-\ind em\hskip 2em} % no_indent % % $Log: pretzel-latex.sty,v $ % Revision 1.4 1997/07/09 10:36:25 gaertner % use \def instead of \newcommand with \pretzel logo in case it's already % defined. % % Revision 1.3 1997/07/09 08:36:19 gaertner % Added Pretzel logo \pretzel to make it available in Texts. % % Revision 1.2 1996/12/03 17:44:26 gaertner % Added documentation, handles obeylines, but still doesn't work % with noweb. % % Revision 1.1 1995/09/05 15:09:18 gaertner % Initial revision % % pretzel-2.0n-2/doc/styles/pretzel.sty0000644000000000000000000000527006236071367016407 0ustar rootroot% $Id: pretzel.sty,v 1.5 1995/02/23 10:26:34 gaertner Exp $ % % global macros for the documentation of the % Studienarbeit % % other styles % %\input titlepage.sty \input a4.sty %\input bigchap.sty \input makeidx.sty % % some logos % \def\WEB{{\tt WEB}} \def\CWEB{{\tt CWEB}} \def\TANGLE{{\tt TANGLE}} \def\WEAVE{{\tt WEAVE}} \def\pretzel{{Pretzel}} \def\CTANGLE{{\tt CTANGLE}} \def\CWEAVE{{\tt CWEAVE}} \def\C{{\sc C}} \def\CPP{{\C\raise1pt\hbox{++}}} \def\ALGOL{{\sc Algol}} \def\LISP{{\sc Lisp}} \def\PASCAL{{\sc Pascal}} \def\UNIX{{\sc UNIX}} \def\t#1{{\tt #1}} % short form for typewriter style % filecontents - display contents of an example file in text % to be done % macros for formatting the examples \newenvironment{inp}{% % input of an example \flushleft % examples are flushed left \leftskip 1em % but indented a bit \catcode`\_=12 % typeset underlines \tt % use typewriter type }{% \endflushleft } \newcount\ind % counter for counting amount of indentation \newenvironment{outp}{% % output of prettyprinted text \flushleft \leftskip 1em \sfcode`;=3000 % a `;' acts like a period \pretolerance=10000 % no second pass for paragraph makeup \hyphenpenalty 10000 \exhyphenpenalty 10000 % no hypenation \global\ind=0 % reset indentation \hangindent=\ind em % standard left indentation for rest of para \hangafter=0 % align all lines \parindent=0pt % no extra para indentation \noindent\kern \ind em % get into horizontal mode \ignorespaces }{% \endflushleft } \def\id#1{\mbox{\it#1\/}} % identifiers in italics \def\fmt#1{\mbox{\it #1\/}} % format commands also \def\res#1{\mbox{\bf #1}} % reserved words in boldface \def\ass{\mbox{${}\mathrel{:=}{}$}} % assignment operator %\def\andsign{\mbox{$\wedge$}} % and sign \def\andsign{\res{and}} \def\myindent{\advance\ind by1} % indent \def\myoutdent{\advance\ind by-1} % outdent \def\myforce{\par\noindent\kern\ind em} % forced line break \def\mybackup{\hspace{-1em}} % backup one em % % $Log: pretzel.sty,v $ % Revision 1.5 1995/02/23 10:26:34 gaertner % Added LISP logo. % % Revision 1.4 1995/02/21 09:11:19 gaertner % Removed mkWEAVE and makeWEAVE macros and those for Oppens text. % Introduced a new pretzel macros to witness the name change. % % Revision 1.3 1995/01/19 15:21:50 gaertner % Included the a4.sty again. Removed \preFLEX and \preBISON % definitions. Have to remove them from the main text too. % % Revision 1.2 1994/10/07 10:27:54 gaertner % This was the original fwmac.sty file. Only added the RCS fields % for Id and Log. % % pretzel-2.0n-2/index.html0000644000000000000000000000410206360634164014055 0ustar rootroot Index file for directory "pretzel" of Pretzel distribution

Index file for directory "pretzel" of Pretzel distribution

Files and directories are:

this directory
    Main directory of the Pretzel distribution
COPYING
    Copying Conditions (GNU GPL)
Makefile
    Top Level Makefile
README
    README file of Pretzel
TODO
    List of things to do
alloca.c
    Fix to the GNU malloc function
attr
    The Attribute class
bin
    binaries
contrib
    Contributed software (noweb stuff is here)
diary
    Diary of Pretzel
diary-1.1
    Diary of Pretzel up to version 1.1
doc
    Documentation (PretzelBook is here)
fgrammar
    Prettyprinter generator function
ftokens
    Prettyprinting scanner
include
    include files for runtime library
index.html
    this file
index.list
    list of files for index.html
languages
    example plain Pretzel grammars
main
    The main Pretzel program
man
    Manual pages
output
    The Output class
pretzel-it
    The pretzel-it shell script

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 09:06:28 MESZ 1997 pretzel-2.0n-2/TODO0000644000000000000000000002113206620644433012551 0ustar rootroot TODO for Pretzel - change bigforce definition to: \def\pretzelbigforce{\par\smallskip\noindent\kern\ind em} % bigforce - the ITI installation still has an #include"../pascal/ptokdefs.h" in the pscan.h header. Make a new installation?! - write examples for fgparse.nw - FAQ: illegal identifier in ft file because forgot to quote the space in the regexp - pretty.nw sends some strange characters to prettyprint() when a code chunk has ended. What characters are this? (see c.ft, currently fixed by ignroing all characters that can't be matched.) - add [[unescaped]] function to pretzel library. Occurs in ftscan.nw and fgscan.nw. Possibly rename it. - it seems the formatted grammar can't have empty rules, e.g.: foo : bar {aaa} | {bbb} ; Also, the `make regression' in main fails because of that! - handle comments - update C prettyprinter in languages/cee - document the faeture of the prettyprint() function: it returns the return value of the last call to yyparse(), i.e. 0 if all went well and 1 on a syntax error. - add lx2l to pretzel-it call to have threads in formatted grammar/tokens. Problem: should use different suffix to stay backwards compatible to pretzel (e.g. fgl instead of fg) lx2l is in contrib/plugge; example of usage is on sun25:Java/prettyprint - Fehlermeldungen anpassen damit sie in ein Raster fallen, welches noerr kennt. - Heuristiken, die auf Fehler in der Eingabedatei hinweisen, z.B.: o backslash nicht doppelt: \textbf statt \\textbf noweb extensions: - reimplement Norman's ideas in pretty.nw (i.e. choose prettyprinter depending on chunk name; at the moment everything is mangled using one prettyprinter). - document the fact that the prettyprinter outputs stuff in verbatim if the parse failed Pretzelbook: - Spell Marc's name correctly in the index - document feature that an empty right side of a grammar rule always has semantic value "null" - document feature that -d produces .output file and tell how to read it. - say how to deal with more than ten semantic values in a rule ($10?): split into several rules! - discuss problem of common sequence "cancel outdent force" and that it would be nice to change preprocessing to tug a following indent in fromt of the force (but this depends on a particular style of prettyprinting, as Knuth's grammar's don't need the sequence that much) - thank Martin J Hirzel and Micheal Plugge, Anthony Towns, David Wilson Mails that contain suggestions: ------------------------------------------------------------------------ > I am not sure whether dpp and Pretzel hunt down header files for typedef > (and class) definitions to aid typesetting, as CWEBx and mCWEB do; it is > certainly not a trivial task, given the (entrirely useless) complication > of the syntax of C declarations. It seems that mCWEB adds some > C-specific features for organising multi-file projects, like automatic > generation of interfacing header files; this might be difficult in a > generic system, if you want to do it reliably (not making assumptions > about structure of the source code). If there are things that require > information that is present in different phases of processing, this > would involve more of a headache to implement using simple filters than > in one integrated program. One such thing might be to create an index > for C++ that somehow reflects the class hierarchy, for instance > discriminating equal identifiers when they refer to members of different > classes (not that this is currently done in any CWEB variant, or other > LP system for that matter). I hope this gives some indication of what I > hinted at. From felix@informatik.th-darmstadt.de Wed Apr 1 18:46:17 1998 >From felix Wed Apr 1 18:46:17 1998 Received: from isasun25 (2414@sun25 [130.83.25.3]) by mail.isa.informatik.tu-darmstadt.de (8.8.8/8.7.1) with SMTP id SAA04187 for ; Wed, 1 Apr 1998 18:46:17 +0200 (MET DST) Sender: felix@informatik.tu-darmstadt.de Message-ID: <35226F57.788A@informatik.th-darmstadt.de> Date: Wed, 01 Apr 1998 18:46:15 +0200 From: Felix Gaertner X-Mailer: Mozilla 3.01Gold (X11; I; SunOS 5.5 sun4m) MIME-Version: 1.0 To: felix@informatik.tu-darmstadt.de Subject: [Fwd: Multiple languages in one noweb file (was: noweb language independance)] Content-Type: multipart/mixed; boundary="------------515461535270" Status: RO This is a multi-part message in MIME format. --------------515461535270 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit -- =========="=================================================== Felix C. Gartner felix@informatik.tu-darmstadt.de Computer Science Department TU Darmstadt, Germany --------------515461535270 Content-Type: message/news Content-Transfer-Encoding: 7bit Content-Disposition: inline Path: news.tu-darmstadt.de!news.hrz.uni-kassel.de!news-fra1.dfn.de!Cabal.CESspool!bofh.vszbr.cz!howland.erols.net!ais.net!uunet!in1.uu.net!hearst.acc.Virginia.EDU!murdoch.acc.Virginia.EDU!nr From: Norman Ramsey Newsgroups: comp.programming.literate Subject: Multiple languages in one noweb file (was: noweb language independance) Date: 31 Mar 1998 16:37:40 GMT Organization: University of Virginia Computer Science Approved: Litprog auto-moderator Message-ID: <6fr64k$6i$1@murdoch.acc.Virginia.EDU> References: <6fpj59$hu$1@news.interlog.com> NNTP-Posting-Host: ares.cs.virginia.edu Errors-To: /dev/null Originator: nr@ares.cs.Virginia.EDU Xcanpos: shelf.01/199805102201!0011729493 Xref: news.tu-darmstadt.de comp.programming.literate:4566 In article <6fpj59$hu$1@news.interlog.com>, Francky Leyn wrote: >I'm using noweb to maintain a library of filters (much the same >way noweb is operating) in multiple languages. These include: >C, Perl, AWK, sh, and ProLog. These filters are documented in >a SINGLE noweb file... >1) Executable code, yes/no > One has to be able to make the difference between exectutable > files and files that aren't. This is a Unix-ism, and in my opinion, a red herring. If your operating system is so broken that it can't recognize an executable script without being told chmod +x mumble, it's not noweb's job to fix it. >2) line directives [different for each language] >3) (optional) pretty printing [different for each language] and also 4) Indexing for each language. The architecture of noweb supports this, but nobody has gone the extra mile to make it work. Here's a sketch of what's needed: A) Identify the programming language used in each chunk. For preference I would do that as: A.1) Identify the languages used in each root chunk. A.2) Propagate the information from uses to defs For A.1, the cool way to do it is to look at the tokens in the chunk and identify the language that way. The easy way to do it is to develop a naming convention for root chunks. It would be sensible to use the same conventions that are used in Makefile, e.g., <>, <> C <>, <> Modula-3 <>, <> Standard ML <> Icon And for languages that don't have Makefile conventions, one could play a couple of games with naming: <> Perl Script named htmltoc <> Awk script named noidx <> Bourne Shell script named nocount And so on. If someone reading this group would care to coordinate an effort to develop a naming convention, I will enshrine it in the Hacker's guide. Then somebody has to write filters A.1 and A.2, which will decorate each code chunk with an @language directive. Then, to implement the desiderata above, we need For 2), a more intelligent version of the noweb script. I will try to include this as part of noweb 3, which should include support for making this lightning fast (ha ha ha). For 3), people who write prettyprinters should avoid touching chunks that are labelled with an incompatible @language directive. (By continuing to prettyprint unlabelled code chunks, they will preserve existing behavior in cases where the language hasn't been determined explicitly.) For 4), if somebody prods me, I will modify autodefs to avoid touching chunks that are labelled with an incompatible @language directive. In a more ambitious world, I should make finduses sensitive to @language as well---and if I have a really good day, I should combine all autodefs into a single filter (don't hold your breath). Note that I have no time for any of this :-) Norman --------------515461535270-- pretzel-2.0n-2/attr/0000755000000000000000000000000010765026553013036 5ustar rootrootpretzel-2.0n-2/attr/attr.nw0000644000000000000000000010111610111701037014334 0ustar rootroot% This is a file written using noweb % % $Id: attr.nw,v 2.0 1996/12/16 17:04:57 gaertner Exp $ % \documentclass{article} \usepackage{a4,pretzeldoc,version,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{The Attribute Class} \author{Felix G\"artner} \maketitle \begin{abstract} This text introduces a new \CPP\ class called [[Attribute]] that implements attributes for an attribute grammar used for prettyprinting programming language source code. \end{abstract} \tableofcontents \section{Introduction to the Attribute Class} The following sections describe the \begin{bigspecs}elaborate\end{bigspecs} specification \begin{impls}and implementation\end{impls} of a new \CPP\ class called [[Attribute]]. It was designed as part of a project to build a program that should produce a general purpose prettyprinter from a formal specification of a programming language. This class is used in the generated prettyprinter to accompany the parsing and build up the prettyprinted output. <

>= #ifndef ATTR_H #define ATTR_H <
> <> <> <> #endif @ \begin{impls} The implementation of the class will be described simultaneously with the presentation of the specification. The implementation will start off from this noweb chunk. <>= #include"attr.h" /* include own header */ <
> <> <> @ \end{impls} The rest of this text will contain: \begin{itemize} \begin{bigspecs} \item A section containing a first look at the general idea of parsing with attribute grammars. \end{bigspecs} \item A general overview over the class interface. \item A detailed description of the class interface\begin{impls} together with its implementation\end{impls}. \begin{bigspecs} \item Finally, a few examples for using attributes are given. \end{bigspecs} \end{itemize} \begin{bigspecs} \section{Parsing with Attribute Grammars} Attribute grammars are a common subject in today's world of computer science. They are used heavily in compilers to generate a machine internal representation of the syntax of a given programming language. The general idea of an attribute grammar is that every grammar token has an associated value (an {\em attribute}) attached to it. If a grammar rule fires, then the attribute value of the new token is found by putting together the attributes of the reduced tokens accoring to a set of rules, that are seperate from the grammar. These attribute rules form a second set of rules that accompany the grammar rules. This changes a normal formal grammar into an attribute grammar. The object class presented in this text is a realization of such attributes. These attributes were written to work together with a simple parser generated by a parser generator. Attributes can be created (e.g.~when terminal tokens are processed) and existing attributes can be formed into a new attribute by joining them together (e.g.~when a grammar rule fires). In this way the parser generates an ``attribute image'' of the parsed text that reflects the syntax of the source text, but doesn't necessarily have to look like the syntax tree that is implicitly defined by the grammar rules that the parser chooses. The attributes that are specified here are specialized for their only task of prettyprinting. They can basicly hold strings or format commands. Format commands can be viewed as a small set of simple typesetter commands (like ``begin a new line''). They are explained in more detail in the specifications of the [[Output]] class that is also part of this project. For short simply think of format commands as an instance of an enumeration type. \end{bigspecs} \section{Specification Overview for Attributes} \begin{bigspecs} The [[Attribute]] class consits of one abstract base class and three derived subclasses. Why three? Well, of course there have to be at least two subclasses, i.e.~instances of attributes that are strings and others that are format commands. They are called [[Text_attribute]] and [[Format_attribute]]. The third subclass is called [[Attributelist]] and contains a list of [[Attribute]]s (so the members of such a list can be any type of attribute, especially [[Attributelist]]s again!). This allows putting together attributes easily when new attributes have to be created. So an [[Attribute]] can be adjoined with other attributes to become a new, larger attribute. Thus, attributes can be of arbitrary size. \begin{figure} \begin{center} \leavevmode \setlength{\unitlength}{0.012500in}% \begin{picture}(205,81)(8,708) \thinlines \put( 90,757){\line( 2, 1){ 28}} \put(131,771){\line( 0,-1){ 49}} \put(145,771){\line( 4,-3){ 32}} \put( 45,779){\makebox(0,0)[b]{abstract base class}} \put(105,776){\framebox(58,13){}} \put(134,780){\makebox(0,0)[b]{[[Attribute]]}} \put(130,712){\makebox(0,0)[b]{[[Attributelist]]}} \put( 30,724){\makebox(0,0)[b]{derived}} \put( 29,708){\makebox(0,0)[b]{subclasses}} \put( 84,745){\makebox(0,0)[b]{[[Format_attribute]]}} \put(180,736){\makebox(0,0)[b]{[[Text_attribute]]}} \end{picture} \end{center} \caption{Derivation structure of the attribute class.} \label{attrfig} \end{figure} The derivation structure from the previous section suggests that we have to deal with four different classes here, three of which are derived from the first. This base class is the [[Attribute]] class. Use it if you're not sure about the actual type of attribute that you are going to use. Also, you can use any subclass object in its place, i.e.~if an [[Attribute]] type object is required, you can use a [[Text_attribute]] or [[Format_Attribute]]. \end{bigspecs} To build attributes while parsing with an attribute grammar, there are two main functions that do the job. The first one creates an attribute from a string or format command. The second one joins two attributes together and forms a new attribute consisting of these two. Table \ref{tab:usage} gives an overview over the usage: \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{ll} [[create(char* s)]] & $\longrightarrow$ [[Attribute*]] \\ [[create(const char* s)]] & $\longrightarrow$ [[Attribute*]] \\ [[create(Format_command f)]] & $\longrightarrow$ [[Attribute*]] \\ [[join(Attribute* a1, Attribute* a2)]] & $\longrightarrow$ [[Attribute*]] \\ \end{tabular} \caption{Overview over attribute manipulation commands.} \label{tab:usage} \end{center} \end{table} Note that they are simple global functions and not member functions of the attribute class. They are simply shorthands for invocations of [[Attribute]] member functions and so belong to the ``attribute toolbox'', as you might say. Note also that all functions return pointers to attributes. This allows efficient implementation. The [[join]] function also takes pointers to attributes, so you can simply say $$\hbox{[[a=join(create("foo"),create("bar"));]]}$$ to create an attribute that contains the two texts ``foo'' and ``bar''. As the above functions are enough to deal with attributes, we'll only mention a third handy funtion here that you might need. It can be used to output the contents of an attribute to an output stream. \begin{center} \begin{tabular}{ll} [[print( Output& otp )]] & $\longrightarrow$ [[void]] \\ \end{tabular} \end{center} From the three functions it is the only member function of the attribute class. So, say you have an existing attribute $a$ and you want to look what's inside, you simply have to call $$\hbox{[[a.print(outp);]]}$$ and it will send the contents of the attribute to the given output object. If you don't know, what such an object is, read the specifications of the output class, that also is part of this project. For the time being you can think of an output object as an output stream, that does automatic handling of format commands. \section{Specification Details for Attributes} Now that we've seen an overview, we can go for the rest of the goodies. \subsection{Details of [[Attribute]]} Here is the declaration of the abstract base class [[Attribute]]. The abstract base class defines two virtual member functions, that are automatically inherited by its subclasses. \begin{enumerate} \item The first member function is a simple constructor that takes an initializing value as parameter. \item The second member function is called [[print]] and is used to output the contents of an attribute. This is done using an object of type [[Output]], that was specially designed for outputting attributes to an output stream. \end{enumerate} For this reason we mustn't forget to include the output class here. <
>= #include"output.h" @ Though I am not quite happy with ``[[print]]'' as name of the outputting function, I'll stick with it now. Maybe it would be nice to use an overloaded insertion operator `[[<<]]' for the output of an attribute to an [[Output]]. <>= class Attribute { public: Attribute(); /* The constructor */ virtual ~Attribute() { } /* The destructor */ virtual void print(Output&) = 0; /* The output function */ }; @ \begin{impls} The abstract base class [[Attribute]] is quite easy to implement. As the [[print]] function is declared virtual, only the constructor needs to be implemented. We won't use the constructor for the abstract base class and I'm not sure if this even is allowed. So the final implementation of the function is empty. <>= Attribute::Attribute() { /* empty! */ } @ \end{impls} \subsection{Details of [[Text_attribute]]} We have seen that there are three subclasses of the abstract base class [[Attribute]]. Let's look at the derived class [[Text_attribute]] first. A [[Text_attribute]] handles a simple string, that is text in \C\ terms. The string is copied into the attribute so you can safely re-use the character pointer that you pass on to the [[create]] function after creation. \begin{impls}The string is hidden as a private member inside the body of the attribute.\end{impls} The contents of this string can only be changed once, that is during the creation of the attribute. So you can say for instance: $$\hbox{[[Text_attribute ta="some text";]]}$$ and you will get an attribute that handles the specified string internally. <>= class Text_attribute : public Attribute { public: Text_attribute(const char*); void print(Output&); ~Text_attribute(); private: TEXT_ATTRIBUTE_CONTENTS contents; // for safety: Text_attribute(); Text_attribute(const Text_attribute&); const Text_attribute& operator=(const Text_attribute&); }; @ The [[TEXT_ATTRIBUTE_CONTENTS]] are opaque within the specification. Consider them to be a [[void*]]. \begin{impls} The contents are really a \C\ string. But this is only known to the reader of the implementation (though it shows in the extracted header file). With this definition of the [[TEXT_ATTRIBUTE_CONTENTS]] macro the private member [[contents]] becomes a [[char*]] \C\ string. <>= #define TEXT_ATTRIBUTE_CONTENTS char* @ The constructor for a [[Text_attribute]] allocates new memory for the string it is destined for and copies this string into it's own memory. Care is taken that allocation actually takes place. <>= Text_attribute::Text_attribute(const char *z) { int len = strlen(z); contents = new char[len+1]; /* allocate new storage */ assert(contents != 0); /* check if memory has run out */ strcpy(contents,z); /* store the string */ } @ Of course we need the {\tt assert.h} and the {\tt string.h} headers to do this. <
>= #include #include @ Implementing the [[print]] function is very simple because the problem of printing is handled by the [[Output]] object handed over to [[print]]. See the specifications of the [[Output]] class for details. We can't just send the string to an output stream, because format commands (see below) have to be interpreted too. <>= void Text_attribute::print(Output& out) { out.do_output(contents); } @ The destructor simply releases any memory allocated for the [[contents]]. <>= Text_attribute::~Text_attribute() { delete contents; } @ \end{impls} \subsection{Details of [[Format_attribute]]} The main type of attributes you will use will be text attributes that have been described in the preceding subsection. The other type of attributes are called format attributes and contain a so called {\em format command}. Format commands influence the way, in which the generated code is output by the [[Output]] type object and the typesetter. For details please see the main part of the documentation of the project or the specifications of the output class. Attributes that store format commands are objects of the class [[Format_attribute]]. Format attributes store a format command. Format commands are of type [[Format_command]]. This type is declared as part of the output class header file that has been included earlier. <>= class Format_attribute : public Attribute { public: Format_attribute(Format_command); /* constructor */ void print(Output&); ~Format_attribute(); private: FORMAT_ATTRIBUTE_CONTENTS contents; // for safety: Format_attribute(); Format_attribute(const Format_attribute&); const Format_attribute& operator=(const Format_attribute&); }; @ The private contents of format attributes are opaque. Consider them to be a [[void*]]. \begin{impls} If you look at the implementation, the contents are in fact a simple [[Format_command]]. This turns the private member [[contents]] into a format command accessible by the member functions. <>= #define FORMAT_ATTRIBUTE_CONTENTS Format_command @ From the previous chunk it is clear, that instead of storing a string (like the text attribute does) a format attribute stores a format command. Such a command normally can be represented by a single integer (as an enumeration type) and so the implementation of [[Format_attribute]] is even simpler than that of [[Text_attribute]] in that no memory allocation has to take place. (For more information on format commands confer the specifications of the [[Output class]].) <>= Format_attribute::Format_attribute (Format_command f) : Attribute () { contents = f; /* store the format command */ } @ The [[print]] function is as simple as above. <>= void Format_attribute::print(Output& out) { out.do_output(contents); /* output the format command */ } @ The destructor is empty, since a format command doesn't contain any memory from the heap. <>= Format_attribute::~Format_attribute() { } @ \end{impls} \subsection{Details of [[Attributelist]]} Here comes the interesting bit of the [[Attribute]] class, namely the subclass [[Attributelist]]. Simply spoken, an [[Attributelist]] is a list of attributes. But an [[Attributelist]] is itself an attribute again, so an [[Attributelist]] object can itself appear as a link in the chain of attributes again. Got it?! This subclass is the only one to have more public members as the others. Of course there are again the constructor (that takes an attribute and creates a list with one element); we have again the [[print]] member function to output the contents of the list to an [[Output]] class object. But there is also a new function [[append]] that takes an attribute and appends it to the current list of attributes. <>= class Attributelist : public Attribute { public: Attributelist(Attribute*); /* constructor */ void print(Output&); /* outputs a list of attributes */ void append(Attribute*); /* appends an attribute to the list */ ~Attributelist(); private: ATTRIBUTELIST_CONTENTS contents; // for safety: Attributelist(); Attributelist(const Attributelist&); const Attributelist& operator=(const Attributelist&); }; @ The contents of the [[Attributelist]] are opaque. Consider them to be a [[void*]]. \begin{impls} Looking at the implementation, you'll see that the contents of an [[Attributelist]] are in fact two things: A pointer to an [[Attribute]] which is one element of the list and a pointer to another [[Attributelist]]. From this we see that the subclass implements a simple linked list. <>= #define ATTRIBUTELIST_CONTENTS struct { \ Attribute* listenelement; /* contents of this link */ \ Attributelist *next; /* pointer to the rest of the list */ \ } @ The main task of implementing the type [[Attributelist]] is the implementation of a simple linked list. The constructor creates a list of one element and sets the [[next]] pointer to [[NULL]]. <>= Attributelist::Attributelist(Attribute* a) : Attribute () { contents.listenelement = a; contents.next=NULL; } @ The [[print]] routine runs through the list and calls the [[print]] function of every subsequent element of the attribute list. It would be nice to have a recursive version of this function, but this turns out to be quite difficult. You would need a seperate recursive function that takes a list as argument, wouldn't you? The [[this]] pointer is an implicitly defined pointer to the current object whose member function you are currently using. This instance of the [[print]] member function actually ensures that the ``tree'' of attributes is traversed completely when doing [[print]]. <>= void Attributelist::print(Output& out) { for (Attributelist *i=this; i!=NULL ; i=i->contents.next) { i->contents.listenelement->print(out); } } @ Here is the implementation of the [[append]] member function. It is a recursive function that appends an attribute [[a]] to the current list. If this list (where [[a]] should be appended) is empty, it creates a new list node and sets the contents of this node to [[a]]. The [[next]] pointer of the current list is then pointed to the adress of this new list node. If the list (where [[a]] should be appended) is not empty, [[a]] is appended to the list that is pointed to by the [[next]] pointer. <>= void Attributelist::append(Attribute *a) { if (contents.next!=NULL) { contents.next->append(a); } else { Attributelist *neu = new Attributelist ( a ); assert(neu!=0); contents.next=neu; } } @ An [[Attributelist]] contains a pointer to an Attribute (which are the real contents of this list item) and a ``next''-pointer to the following list item (or a [[NULL]] pointer if it's the last item on the list). So the desctructor doesn't have to free any allocated storage, but it has to take care that the {\em entire} list is destroyed. The way to do it is to destroy the following list first before itself is enters the graveyard. <>= Attributelist::~Attributelist() { if (contents.next != NULL) { delete contents.next; } } @ \end{impls} \subsection{Details of Functions to Handle Attributes} All actions on attributes (creating them and joining them together to form new ones) can be performed using two overloaded functions. These functions are called [[create]] and [[join]] and will be presented in this section. So forget about constructors and private members of normal attributes. The only things you should remember are what attributes are and how the following two functions work. The first useful function to handle attributes is called [[create]] and does nothing but to, well, ``create'' an attribute. You can pass either a simple string to this function or a format command name and the function will return a pointer to the attribute containing the passed information. The storage space connected with this attribute is allocated dynamically and will not be deleted until the program using this function terminates. Since some systems don't free the dynamic memory when a program exits this doesn't make sense. This might be a point for future work. So here is the function that creates an attribute from a string. <>= Attribute* create (const char *); Attribute* create (char *); @ \begin{impls} Here is the code implementing the first instance of the |create| function. Called with a string, [[create]] creates a [[Text_attribute]]. <>= Attribute* create (const char *z) { Text_attribute *t = new Text_attribute(z); return t; } Attribute* create( char* z ) { Text_attribute *t = new Text_attribute(z); return t; } @ \end{impls} The next instance of [[create]] is for format commands. <>= Attribute* create (Format_command); @ \begin{impls} In the implementation, called with a format command, the function creates a [[Format_attribute]]. In both cases a pointer to this attribute is returned. <>= Attribute* create (Format_command i) { Format_attribute *f = new Format_attribute(i); return f; } @ \end{impls} For example, now you can say % \begin{quote} [[Attribute *a;]]\par [[a=create("any text\n");]]\par \end{quote} % or % \begin{quote} [[Attribute *b = create(force);]]\par \end{quote} % where [[force]] is the name of a format command. These two examples will create an attribute [[a]] that holds the text line ``any text'' (and a newline) and an attribute [[b]] that contains the format command [[force]]. \begin{impls} It is important to know that the [[create]] function that takes a string invokes the constructor for [[Text_attribute]] and thus the given string is implicitly copied into the attribute itself. So: \end{impls} You can safely re-use the string pointer passed as an argument to [[create]]. \medskip The next and final function to handle attributes is called [[join]]. With this function you can, well, join two attributes together forming a new attribute. \begin{impls}Actually an attribute list containing these two attributes is created. But an attribute list is again an attribute \ldots\end{impls} First have a look at the [[join]] function with two arguments. <>= Attribute* join(Attribute *a1, Attribute *a2); @ So if you have two attributes (as pointers), say [[a]] and [[b]], you can build a new attribute [[c]] by simply saying % \begin{quote} [[c=join(a,b);]] \end{quote} \begin{impls} If you look at the implementation of [[join]], you will notice, as this attribute [[c]] is actually an attribute list (but nevertheless an attribute), [[c]] is also allocated once and for all and will never be deleted unless the program terminates. Here's the implementation: Called with two parameters [[a]] and [[b]], [[join]] simply creates an attribute list with [[a]] and appends [[b]] to it. <>= Attribute* join (Attribute *a1, Attribute *a2) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); l->append(a2); return l; } @ \end{impls} @ However, instead of joining two attributes together, you can also join three, four, five, \dots, and up to ten different attributes together with the same function. Since the following definitions are nearly all the same, feel free to skip the following text until the next section begins. <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8, Attribute *a9); Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8, Attribute *a9, Attribute *a10); @ If anybody knows a way to get around this way of defining this thing, I'd be grateful for a short notice. \begin{impls} The implementation of the [[join]] is possibly the trickiest thing in this whole document. A first idea would be to implement all the calls of [[join]] with more than 2 arguments in a way that relies on the version with two arguments. This means that a call of $$\hbox{[[join(a1,a2,a3);]]}$$ would be done by first calling a joining operation on the first two arguments and then joining the result of this first operation with the last attribute, i.e. doing: $$\hbox{[[join(join(a1,a2),a3);]]}$$ This however would result in attribute trees that look like binary trees and would create ``deeper'' trees that also consume more memory, because you need more ``nodes'' in your tree. The goal in the current implementation is to raise the branching factor of the trees to minimize the depth. This is done by making the lists of attributes longer. Always going back to the simple [[join]] function would always result in lists of maximum length 2. Here we`ll try to raise the maximum to something around 10. <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ We'll use a nice trick to spare us typing the stuff in again and again. The {\tt noweb} system allows us to re-use section code. The following code is part of all subsequent [[join]] implementations. <>= l->append(a2); l->append(a3); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a4); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a5); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a6); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a7); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a8); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8, Attribute *a9) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a9); @ <>= Attribute* join (Attribute *a1, Attribute *a2, Attribute *a3, Attribute*a4, Attribute *a5, Attribute *a6, Attribute *a7, Attribute *a8, Attribute *a9, Attribute *a10) { Attributelist *l = new Attributelist(a1); assert(l!=NULL); <> return l; } @ <>= <> l->append(a10); @ \end{impls} After testing and using the [[join]] function I have noticed that it would be very convenient to also have the following function. <>= Attribute* join (Attribute *a1); /* simply returns [[a1]] */ @ \begin{impls} This is implemented easily as: <>= Attribute* join (Attribute *a1) { return (a1); } @ \end{impls} \begin{bigspecs} \section{Examples} Now that we have learned everything about attributes, let's have a look at a small example how attributes are actually used in the prettyprinter. This chapter depends heavily on the information of the main documentation of the ``pretzel'' project. They refer to the environment in which the attributes of this class are used in real life. If you have problems understanding this section, then look there first and return to this text later. But I can already say that you've learnt everything there is to know about attributes already and that you might as well skip the rest of this document without loss of confidence. Suppose we have a prettyprinting grammar that suffices the demands described in the main part of the project in the chapter on file formats (``formatted grammar file''). Say we have a rule % \begin{verbatim} block : BEGIN stmt_list END \end{verbatim} % that defines how a statement is formed and say we have a corresponding rule for creating the attributes like: % \begin{verbatim} $1 + force + $2 + $3 \end{verbatim} % This will be transformed by the prettyprinter generator into \CPP\ code similar to\par \medskip \$\$[[=join(]]\$1,[[create(force)]],\$2,\$3);\par \medskip\noindent as code for the action to the rule above in the BISON file. \end{bigspecs} \section*{Identifier Index} \begin{multicols}{2} \nowebindex \end{multicols} \end{document} % % $Log: attr.nw,v $ % Revision 2.0 1996/12/16 17:04:57 gaertner % *** empty log message *** % % Revision 1.4 1996/09/02 16:04:06 gaertner % Added destructor bodies so that g++ won't complain. % % Revision 1.3 1996/03/18 11:19:03 gaertner % The `const' declaration had to be extended to Text_attribute. % % Revision 1.2 1996/03/18 11:09:08 gaertner % Changed declaration of `create' to `create( const char* )' because % the const is needed when using flex scanner classes. % % Revision 1.1 1996/03/07 17:39:28 gaertner % Initial revision % % % pretzel-2.0n-2/attr/attr-specs.dvi.gz0000644000000000000000000002171006255300321016232 0ustar rootroot‹Ñ€µ2attr-specs.dviä[ pÕ‘^ï®ð¿LøõÙ ËÈk­, ’!Xgcã"¶I¼œ‚ÙÝYíàÙ™Õ̬¤ _¡lM´šxdÈÚ僋ÃÏr!û8c0øˆ¹äâ»ã7$\Ñ]8ˆ¯»ß›Ÿ]IÄ÷W•JT1%ͼ×ý^¿î¯¿î7ùmxÂWþîœe!ø‰¼söÜ„xí\µ`ä ÆÜx[ÛÒX¼%_Ú¿¤¹eŒ˜:‰Ÿð³+|(êÛõñŠPhW¸L¿> ÷ „ì_Ι¹ò•÷ŒÐ¬ÕÓ¿ºTN‹_üd"+ÚuýÛ» C“’C´VÈ‚®›åsCúðg 4ôóÛG>uí·??54 á?šÝòÔªÒ‰º/вÔ[мûàê­¥çFÍPDÍÄŸòg¾¾ fûø‡+Å”˜ëß«%û7˜¢fÃàøÒ& wj–烚Ч?3r–1í®öÐd?™©Hö¶ý}GR74!e˜å™{ö•Ö•9SýÛm½qQXJÛ³‰¬¤Û‘¶c†ØkX’2¸¿ÍÐÔþŽƒéBJÔ-ÁRÄkäìí‹~wMšÿ&¦r)=o~nE_ùD(ôì…š¥Y÷}9…»·R‚,‹ikäœã¬ ×dm;ãsš2—hÊ”šr˜Ñ” Ò”ÓN}’h ²X#+vtmƒïè•Xiâu—­1¬X•@K‘:àð{HšEú€^”Bæ%7Á‚ñ°“IN³ÇÈ:,d7\‡žU rÚj‡—°!$V0²S¶'ÈV¾ åU9Ù÷:§1Àö`JFSs08ƒð$WoÝ[Ç"®È¥;vøH#0b:±RtåR<‹±3ø…xj³²Eð` íGacB*¥æò‚¶(r=0}>Ïh ³4ß~!OBkE¥K!ÄÑcfyQƒéGWŽÌºåæë&†&ÁIMâlô’á¸ÉXÕôyõMƒA* ãÍû²#õ‡Ú«(‚o~1+–NliÒ¢VŠXoÇ÷IfiÃÝ/ÍÂÇì:OÊ(i1Sª»üãŽDâ 7\É_œ%E >LJ7û²/^)îäBm: ZRRr!-ºÄqðHv&í(7¹”ì‹k…”†bT”‘§)óïq¦Ìo9¸ügbò—¼tùå$ÓŠ‘â|—µ^d§›mпeflÍz›(£dè–^H–Ø[]‡½ ·&«Vº²f®Ž“ÁÅ2ALËÂa—B·ýpÍgéÖðÒ$_ ³¶¨¤¥Œ¹Û,ϳýäW½ µÛ± ŸLA? Ç(ÈnÇú`)Gp)MÔ) to*_z$YFΠЬ´#–…°CÛ7*+,*¥ÈúÓ8ÔØ‘õ³ýäÏÖ4 (­>WÝ û DŠlIiQ@¥®÷“y=[˜MãE ¯Rô˜ùÀic®wà U!Zº-FËwb°Xø—z:.‡…dFHA¡²{aiJGÊ ;ó.FàêyðÓ6?AÎ*I@,b&kB‘<«"Ç"üóþá GêÉ¢›Å*Še‡ÊWCràõ d…ñê—@Zèôó¥=åUפH€ÓÍå`_èÌ.ü¢qð°Ò‚SlЭÈF°sD.¢YzJÜóÒþS´#ÿþ4J$4ÌŠhí–ä" Ãi`H<ÞEHPRNàÆ8 Lei"€Žõ+Å —¯fìÈÑ—)¾‹ nGèe` vr €¬)M9P×½}qb G Ö¾\>7‰]~z>Òb7èµ¢WêfT•…¤…t-”’ë»K'º rA´À»=ñ•FPµˆ+1„ˆÌBvŒ<±Ï€%î¸c íƒ+Ñ ÓÀM¥È‘7`à ÕüZÝ×ÄÓ4_š¤sMµ €–ëM‚Â"$DkxÖ)­Z¤îJÒDL¤i.M§D¥±y°B]Dhà p™¸ÄØ£h+;rþDûH:Eä2ôØuröRųH ¢¨üýÆ!‰çg¥`í(cëŒY=ä„¢–C(óCCZB! BöK7"káŠÄ^¨lŸ¢7^p3_ × r®é®ý&•åØkÎÛ4—Oë²£g¼GK#xc¥S†¿±†ŸIäÁ*â"SÕ¦¢hÞT R¤ÞŽüúe4+ÍΗœQ§ƒ/è¥~”èk…áè¦Rô¬Å ÙJ£±D]ipý[Ñt‚ ¹3|UOV`9Ë1T‡§JG–6ãÈZ ÂŽ¡‰ø@0 ’œ½”’ ¹è ÓNÒ*ÒðjO§ø@?§•Œ‚egI˜*‡¿`fàäXôa„ç±~zEéCsËôvÞ>’f© €¿!è›)¹ƒõpÐg²p±Qi1Ë˶‘‹º”‚©YrŽn Di,† JWàjzÌ¡ú°ú!×bì¨úuælH0š¨Ü€€ 9š¹Ñc8EB.xŠÉÍ•f-û;¢µ‰uJ óT®D†ÄUžVwýÏØòïß„Ö{ó2ð† 9ž0áÔ~fBVsxè;´žø¼UaÕ7¡ë ÷"¢ÈºêUKäׂ "ºÿ>n Ê#E[C˜”:ó‘1 uC€tÎ o8¶B#Ì5PÌmeZB\dCjÔ@/Éúnà'c÷CkJÕºÙw…7»Á$È­a*·ÜÑ+\Ò…å‘‘…8ËjŒ'¥‘¾¸þÅùxÌž<§óš,–Y;£o\D3.·®A#‰²ÜTª[ýžšqR©:…˜&:Á¤3‡"‘EA7 Â–ê€D<¦ Éµ^LŒÙ‘¡e®iñcFwfÜ€Šïj½;H¬¢7©8„ßÔ´­ ŠÕnÚû±Óþ€hdwå>OàÅzäù®ê®“ G1ÈH<Æ =¯ê_U @t֔ȉ9f0M÷’›×ìÈ•ïÓdÿÝ^Eýˆ ½€U\hÅ1<¸zi Tè„%̓ȋæöP¾x¿ÃÝç;väµï{é2ppžÈK)yT%Ýr€M­N‡S¦NÙ úQã/Ìž]¡íÑv„4f/8*ÊÑj­~ »Ss"Ó¦Rø­a¨;ƒÃ|€tV<Œ•KÑvZR‚(®ªa<üÃi#D)’Á )£ `s·¤t·WÇ× ìÉàÞIà –q€iãÚEË|q¸?;rÞ1à›š•–¦B ‘ËXnIŒQºh˜Å+¬µ'+Òxô:˜3Ü•`™ˆDq5+†|0¤í¨¦I,áŽÂ ðöCs6DH@¿2VV¡@‰¢âv4—Z`饀d†ÃšOl¿PŠÜEÛg¢XQ¦r6 %xÃ-©ÀdÈï‹O/:0Ϥ€üVþŒ7µª²tsýT†²±igäι B¶\(øwg ~ñEÄèÀ?º Pö&§ØO+ôÔ×"×VQ5l¹HèΙ¾B o+DN®«0ý©1Ú ož¹½¯üóm}üÎöÐ;O–_ÙÿÓ‘ [ßX¿ßjÂoÞ;É„!¯À#ûJ¿ÿ¤åŽò gG'™&Nþ·§ëÊ#ןu{¨©ãüP(#²§ÿ¹ãÜò‘{þãK0~Büþê™ì÷7?]þÙsßÿŽ*øçµ}¥^»©âf "?‘˜8dýãŒ|ù‰/» ¥‡.нPžúôc}·‡à¿ø¤¯üá¼f©5ö™ßʈÞh’RÞÿÁ éŸê^÷ÏŽ½ø(Õ/ÿbvбwïoÞ}õx¶â'2¶¨Ò-oÉU¹†Mxm÷a˜0¸å›£àž½óÂûßtuÕ8û)Ï¥F¡ôÈ•UR'Äš#Þ^Šv\9Hprâgm&w¢vøž¼eë£;¯MüÆÎ•àþ' O"?„d[‰9@zv÷Ie­Û8³Ãoœ àL³ôs“šØøÜÆÇ¢ ¶õj¼ûË2±Ï*Ýæ5˾ ëÆ±à¹óª"¨ëîêð]¦»yF!œÓk«OðV1²ePMÌ¥Æð0È BRfçƒ-D`ÚˆŠ Ì¸û•¶_СXi7Ë×ÛØW~á^ ¨üÞ[i8ëë–bvXÊ ÚBìËê&…å„Ï<®î ÁIL8÷¥7ç6xNºõ1a¾;ÖmØ0äXÿ3!Ük¹™q1™ÿž<‚þs\o²ü'–Ðr’Ñ…º‚ÜëwUªmN1±ž5€‚ÆöýÖ/å 2 Ÿ´á]à†Å:“HïT·ä*2 È ŽNYMb[Âë£Û`ª"0À¨Tà5óîB~ŽŠèWóì=<”¨ÒQde@–¸>òpI!jƒ÷%)·­_]Eè¬ W{åºü£. ðH•‘Ye©ýϯžá‰£ÊIGÓõÖ7a‘A©1'ufBë‚C­P,#<EÝGµ £ÂrÐ*P44ÅÂô§²fï!û(uGvy,Ðéz7{“ŽÓî1DeQ,dîW·ÑUÙ<{ʪ¸Y‘ePôé®Vg´NHù‰=0ÐÍúîµÙMøåN_i˯.#¿åAPŸQÕúÆ&÷¯¤ Õ76.3͇Nå0Wa=)6 ¾ÈFA^Žæ7œG¥^ƒnmÊP5_Oµ e»¶î€#Œ=C`NLÈ%º±g^ˆõ«¢:³.Ñ«éÆcÏoéWˆ6ÀIQ‰O‘ñ¼Û,(8ìðàlt¾"'.GÄ3Vð EDr]òå5ÁÚȰ vÍÅzî*ž}Ú´Ûk ×4ïð wÀ¼(äbøq^| 1q Ô÷ø÷†°ý`,@ü`e÷@Óó– áÇoæÐ1é¥÷tt«Rš@ƒY³BÅ6$;rß::"¸¾)%"iø†iŒ¸7»zoÒËS×±,)Þ^„­A™Š·ðL·Óæx"œ‘)Sw%?¼ÐËIñæï ÖtÍïAÁ>SœI^ŠèRZ$•8°Ê¯ñ%Xcíˆ>úÞ^sHˆ1‹¢áÑ™9å•v´ùZ‰_$é"•ît’;0šñÓ/0ÊYxîóÔ§À@øÃG×dÈ‘ø:ÓªÒ`Øáßz³‚øuUdæ¸3·ùªTSh`Þ3ïIb_†k¦“ir·ÐˆPö¿#é£Ú2;½EÖ•·ºmò Š>ò¤âîµi„À^”ájã\íÚM§AÔ½²„‚¡B‚•Rt­(ÅÕù‰™eÿJ©u¼6Nõ'iÛ_«‰³ŽÌìõ{±kD]Ä®l¬4á;Úg§êv-ÿ²+«à‡PBb2P,áÕHô䪑9§ŽsÉÉ®ÀϧÏÝïFùgˆ/Ó§s«¶îu?>‰þU?»àøßMF¼å¨Ïî˧Ì WªÙѶÇy¼§E¼òª|Œ.Võçsþ5Q;ÎGVýFºn£&o€‚vÝÖ-iTɾ Žæ ½}^‹Éój«H  ±ä^H¦V•à+³?»…®5—ü®?ãך”=§¯%ª=¦fvÂÉQG,(èà‘ ± î áí=vŽÁUùç¤Þù;Å–! ÃZ>]qܵ´×¾~.çéã®ÆmžL±þ–ûåÆ'%P€×PŠL2¬æÿqø_K~‡[0xöƒ^ñÎÛ»¨uîÝÅÃvç¢ ×ç~ƒûÇXak3j.‰ÇÌspX·Rzâ˜ÃB“š‚v`­œœSÐ €JŒD¨Z‚ß`Ôeì˜ùЧ*÷€Ù'—–· ì{’ÿÝç¡÷ó£ÀÇ$lN=ÿ¤%[oîÞãö‰‘Øáã÷¯)…MÈKî*€ãÆåóȳGÙÄŽ¶R¤S—©p²Ÿëp¿]´¦ù<˜f³ùÚÝüëÐãô~‡·¯ÒÊ( ¦1?=âE‘R"oùx'«`lþë¢Æ0À½U]R}ãÐ¥—VÜó Ø¼ærš²ë:1úLlò›†[“Þ!ü~¹20áœ#¿ô…~ÇãI¾™¿Ë’²”jÇ¿VØå½_и Ç/^h%²ÕQ¿p1Ëá ‡!¡²ià¬ÑºÌj^fñùÜ$^ 3 }Ë2swyî7na þ2}Ÿ; ¾Öt@|´f;#«?òØ &,v§Æ®,âsÕý~GÍÐÝš‹Ò¢4ÿœ$ˆæü”?'¥ÂC®ùî%piÁ3AmCŸÚ .m/E–ÔŒ°#Ë ex1³¬§¿r?û¸·ÑŠux…UÁ\,oz ­Ë»%&—þ”š——²Õ|,Pí@—!hâ"t|ÂL ¤hÀÜ@Õä3}®'Oi,üŽª¸üŽ7'‚X†nàð1Õj“öÞ›¨%Œ(‚“-ÞÈÁe!ÏæŠ(<íÈ¿ucP+õm.¥Þ‘õNÔ:¹¤O성évÙH,c:e¨¹èž)Ê4d+]á«$A£og¦{äí§C¿äáºY ”íç“)cÒ!9qzN²kå¢ >Pö¯ +¤JTúºëW|[+÷Ù_—ð¨r˜AŪ½ÝŠèŠÕMäî%ÜãÙìø!ÉQ±•x4 BuÑ ¦“(^Q\"^ ì¶Ðšr"nJ<:Ÿ?NœásI“—âœf\ÀJík)Ÿ5óöÅq >§{§€’Qf|õ$ÖSÄ¥æ”ÏËb*pƒ¡REa;—»¸Ü@ïÉ7­:‰z#èÄêÕ†1 ’¼´~²˜ùNˆ^lüð¬Ú¥vîÍG Ùàá¼Ô€ý­î«†ã4ŸCÐÊ´ì¤;ÈEîÉ“\¢xèª.¢E¤ÈÕæå;"ôø£žªoRòOp~BΊ Æ#ß «ŠÝ4KýåÉ$¥×ùF)}g ÈÐ~¯Ûç]ÚVu<{1k5¼ÿá}»oÕ^-2šëmˆÒ¿,iµ¹Øa·Än­ZžÝ¸t3»•[ùÖ´†1Ó9Æ•o%™°”öe[Gþ©ª2XŠv¨ŒTbÀÜÖê—µ²ßT¾(³ã*2@Ø£S4rŸ’¹Q±¢^ÑBד—1¼­2Ö䤘2*¥üm;»î©¾`’˜å å7ÿÒ"0ó§b’},¾ê#¡f#rÞ¢ÜáFݯ–ÛÙá—,–;0^áÙzàºß¤ÖzD€§DÝÃ⣠à)Õ&a¡ìŠâ/¢UHÙT°Ô½øú/­MËzïú3°jç6T’¦Ç\e(täú3Dá=‘ÀcÄŸk(ÛŽöâ›§÷—5Æ‹œ²vîcs ¨MSR &­$6ª|ØY…ð«†&_aØ´#òxbÝd¾{'ë¶…rÞ·«•¹<öXäÏÂO !ÀAÙ8“ö‰àc™cra2_L9•G`tÆ5Ù Èr|5ΜvËÊI(Öž™—Ïygˆsi!YÂÔ ×QÞl.bó† U œ»ÒÁ…a ÿ¥¡¢ÇR3 1rw‰ë™çÙà`ÎjÐû,Ž-çË67ÖmÜ}s;Óî´3˜OáíuìÎðÞXãâCøëzG†JK†~ÐwìXÌ iKöõÂèÿÉš¹ÆéøZ›&ëë%˜ëJ±`:/é# fÚ•²µ[ŒáR¬L h$ebðÚ)ƒh»-ˀò ·nü¡ËYûl—Óhƒ³»Z%*¾"ÔÌígXZSíñ°9¹÷8Uj Z4Cͯ÷µ³K¨ß„Âî眸`³p×`q~Tk4,Ó? Bˆä;ÊÀqx£¼XÖ„íÌke¾+÷ø'‡q<:•dœµK2’hìËG•ôÆâ×fÞë:5:ÛÀŒ7y»Î\X£Z ݧW^mÅ”ßÑÚzÞ:¦G kðúñ)Åè>İ!%?¹ã1”Üvv}¸@?о¡+ô±3q“{ä7L¾'Þ¬‹¹ÖZ±¾’ÓÐ'­ƒ ;ÍT%ü/”#$SGG¹« XŠ:ÎŽ7þØÇ~´y’ŠêM¸Îˆü™³&µ,¥zù=uÞJô;ÝèÄ…°ø{JÃJm8Ñ$Š©È?º@k¹ãúw_££‚3è©yÿ…MC'a¾¿Õ=¹ú`JG'FF£/ð ÄSA›FÞ›ZÉ—… Û-НÎçUÀ[|)O3­dŒij±†½b´!Rc$K¥•5ÛþÁyùÆ&ÜÒy°·Ñ&ok_*±³]”ÀËS_ýÆRJMÄ;/ë’]‡’Þ›žÍØìË·rŸh\‡G†¤·8O_jå¡ZŒ Gû¼ã´-”¢y®¡V¤Zx šáD唘Üé勉bøJ@ÇÛG7?›ýç Ôò¾~åC°QÚ¿VJà!‡”Y…D³T"0±äF õœ …éo¯xá…þ¨?ÊÇäÇVÿ-DŠè¥@¸SªÅc‹úKI(­Ÿ_"B×$ÂÒþ4ù¤ç¤ËŒÑ‡Ýצ}gˆÌ«ž—oeŒ”}¿*.HÕ'+ÓÞ-œsFù@ÌaÁg‚ PJª ¹’Iœ¿Ã{_ÏÈ\Ç™ÓgOÆFóT¤‰ýq:s)—ágRà½{Þׇ“Ðyå锩ø`eM4`ß4x;ÌÁþ¸ý6œ’ýqÇí?ÃEDnçÿáÌù!;í˶|ßDlG¡<›™[ÃŽ\‘Y±3ñd,J ð7p bÐÚà+`§Šžå‡ L­(¬Æo)€Ï·2Wî.l—\ÓB¹å¦ªâ,³íIá8£•’®"Ý|dgN %•Ô⩊B+{ªš¤ÏOÍðÓÆ9ž«p5©A¡CÆÜŒ*ò ¸DůUÐýšY¾ä‰l ¬gÚRQÁÆ‚;ÞÃXð– gOÅà E=:rÄÛrì¦LMÏi‡xNÝËóœFÆ–¢;_ n·ê5çàmïÿ—âm+·ª † —}Ú’¤p6Y0æuW‘ߦnôÌîNÒd!‰`$ÄigšEÉj¥ó]T ëc¶R£®g1uŠˆ™$°aîï2¡Ä¸¯PCë¶Cí̃¯5A×t.GÁjÄ$ „F‰Ãë×£8ò·ýêúT‹…ÿk¬d¨Ð/ãÁè•8¡0ߪ„AmŠ¥·œ&*wFŒÊ¦•Õu±€t4Pm“àìÑ\ó*‡N¦4óc<7³Ù×ÿ&ØL­Xõ§ê1(ðw ÂúЋ›Ûôö( \ÓÑó1?HŒ –FP&fZ)sí0G”/úÃWÎ)´2×`OK&Ж6<ÂñÛ å'nXò£ X¨IdÕª<“ÈU;{ÿ%SäùœáK °%¹äÕ9FKÜG«i™¹§\Fà ³^ç6Vµžqî_%‰¨&áKA4ÌÝïZïž-‡øFº#×–|¤ä+æ?S1„#„¢©ò× ²Ÿ¹ßIb1û*ˆ`MqJ¤Z°C˜s”ÿÂ,¡êñÂ#ÀUØ$wòò¨T !¨‹…bl#q &Ô‹Õ 4‰ÚêÞhhÏÞÂëSãäìyÐN üýûRy N/\ ÒÁ;'«0ãOõqû‹…°E´¼$¢Ü¦9”tƒ@J½âP­6z¯Âz·àœ7GœqÙõnÅÿ¶©ù2À onp»B¯V—u먔r‰ts$âR‘ÙâríՖОPWªÔ ìÌs*GÑÛ»À1à|ï–ü‚•*šÏ÷nÍ÷nÓ‘!³dJÔ´Òו0žÎf<ãò <‘˜<‹¡Âèþ)á!-_AÆúœJ¶V–ËP[Ve'X•k]]höyGñ¢uמ®Õ]ÝîZw¹Œ³Ÿ¢»‰ä"ÍCÝý½Ý=Â=ÏéîìÙîjÐîj“éì)ïlSïî©ín¯é®Åsvðv7G¸ÞÕuìO™ßÓ¿ÿÿ\Ž`¨_pretzel-2.0n-2/attr/index.list0000644000000000000000000000041406360136045015033 0ustar rootrootthis directory & Directory of the Attribute class Makefile & Makefile attr-specs.dvi.gz & Attribute specifications attr.nw & Attribute class noweb source attrtest.nw & Attribute class tester noweb source test.output.correct & correct test output for regression test pretzel-2.0n-2/attr/index.html0000644000000000000000000000211706360670274015035 0ustar rootroot Index file for directory "pretzel/attr" of Pretzel distribution

Index file for directory "pretzel/attr" of Pretzel distribution

Files and directories are:

this directory

    Directory of the Attribute class
Makefile
    Makefile
attr-specs.dvi.gz
    Attribute specifications
attr.nw
    Attribute class noweb source
attrtest.nw
    Attribute class tester noweb source
test.output.correct
    correct test output for regression test

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 13:06:37 MESZ 1997 pretzel-2.0n-2/attr/attrtest.nw0000644000000000000000000000276310765024433015261 0ustar rootroot% This is a C++ file written in noweb % $Id: attrtest.nw,v 2.0 1996/12/16 16:45:18 gaertner Exp $ \documentclass{article} \usepackage{noweb,pretzeldoc,version} \includeversion{bigspecs} \includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification %\excludeversion{impls}% without implementation \begin{document} \title{Testing the Attribute Class} \author{Felix G\"artner} \maketitle \begin{abstract} This is a short \C\ program to test the [[Attribute]] class. \end{abstract} \section{Introduction} This program is a short test for a C++ class called [[Attribute]]. It simply plays around with the [[join]], [[create]] and [[print]] functions and outputs something to the screen using the output class. <>= /* attribute tester */ #include"attr.h" #include"output.h" #include int main() { Attribute* a, *b, *c, *d; Latex_cweb_output o(cout); a = create("A simple PASCAL example\n\n"); b = join(create("for"), create(" i:=0 to 10 "), create("do"), create(indent), create(force)); c = join(create("begin"), create(indent), create(force), create("writeln(i);"), create(outdent), create(force), create("end;"), create(outdent), create(force), create("\n\n")); d = join(a,b,c); d->print(o); return 0; } @ \end{document} % % $Log: attrtest.nw,v $ % Revision 2.0 1996/12/16 16:45:18 gaertner % *** empty log message *** % % Revision 1.1 1996/03/07 17:40:03 gaertner % Initial revision % % % pretzel-2.0n-2/attr/Makefile0000644000000000000000000001115706474246771014513 0ustar rootroot# $Id: Makefile,v 2.0 1996/12/16 16:44:14 gaertner Exp $ # ---------------------------------------------------------------------- # # Makefile for Attribute class and testers. # # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = g++ # compiler flags: CFLAGS = -g -I../include -L.. -lpretzel # Groups of files: # all noweb sources NOWEBS = attr.nw attrtest.nw # root chunk name of headers HEADERCHUNK = header # root chunk name of implementation IMPLEMENTATIONCHUNK = implementation # all `WEB' sources (old) #WEBS = attr.spc attr.w attrtest.w # all other program WEB sources (old) ETCWEBS = # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = Makefile test.output.correct # name of the distribution package DISTNAME = # Which program to make by default: PROG = attrtest # objects of this program: OBJS = attrtest.o attr.o # objects to release RELOBJS = attr.o # headers created HEADRS = attr.h # C sources of this program: CSRCES = attrtest.c attr.c # these files can be deleted too if we say `make clean' REST = attr.aux attr.idx attr.log attr.scn attr.tex attr.toc \ attrtest.aux attrtest.idx attrtest.log attrtest.scn \ attrtest.tex attrtest.toc attr.dvi test.output \ attrtest.dvi # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = $(HEADRS) # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) # these are all header files produced from WEBs that may appear ALLHEADERS = $(HEADERS) # these are all the executables that could be produced ALLPROGS = attrtest # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle NOTANGLE= notangle NOWEAVE = noweave TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex -d #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = tex-it latex # ---------------------------------------------------------------------- .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h # overall rules: .nw.tex: $(NOWEAVE) -delay -index $*.nw > $*.tex .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .nw.h: $(NOTANGLE) -L -R$(HEADERCHUNK) $*.nw > $*.h .nw.c: $(NOTANGLE) -L -R$(IMPLEMENTATIONCHUNK) $*.nw > $*.c .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) $(CCFLAGS) -c $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) $(CC) $(CCFLAGS) -o $@ $(OBJECTS) $(OBJS): $(HEADERS) $(CSRCES) # list all source code: #print: # apply lint to all C sources: #lint: # regression: regression: $(PROG) attrtest > test.output if diff test.output test.output.correct; \ then echo "Regression test is fine."; \ else echo "Regression test failed."; \ fi # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(REST) # remove everything that doesn't belong to original source: clobber: clean $(REMOVE) $(ALLPROGS) # bundle source files together into an archive: #bundle: # tar cf $(DISTNAME).tar \ # $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # copy executables into PATH directories, et al. #install: # release headers and object code: release: $(HEADERS) $(RELOBJS) cp $(HEADERS) ../include ar vrus ../libpretzel.a $(RELOBJS) # ====================================================================== # # $Log: Makefile,v $ # Revision 2.0 1996/12/16 16:44:14 gaertner # *** empty log message *** # # Revision 1.6 1995/04/26 17:22:25 gaertner # Making dvi uses LaTeX now. # You can make a regression test now. # Compiling and releasing use lpretzel library. # # Revision 1.5 1994/10/31 19:00:05 gaertner # Now make bundle works and creates attr.tar # # Revision 1.4 1994/10/24 16:46:09 gaertner # Now the attrtest.o object isn't released. # # Revision 1.3 1994/10/07 10:36:46 gaertner # Now all LaTeX intermediates will be removed too if you make clean. # # Revision 1.2 1994/10/04 18:40:44 gaertner # Initial revision of the simple granny version. # # pretzel-2.0n-2/attr/test.output.correct0000644000000000000000000000027606123242064016732 0ustar rootrootA simple PASCAL example for i:=0 to 10 do\pretzelindent{}\pretzelforce{}begin\pretzelindent{}\pretzelforce{}writeln(i);\pretzeloutdent{}\pretzelforce{}end;\pretzeloutdent{}\pretzelforce{} pretzel-2.0n-2/Makefile0000644000000000000000000001107410111701037013505 0ustar rootroot# Global Makefile for the pretzel distribution # $Id: Makefile,v 1.9 1998/12/03 10:31:46 felix Exp $ # this is version... VERSION=2.0n # use which C compiler? CC = gcc # Installation paths: (currently set to my personal settings) # target path for libraries and objects: #LIBPATH=/users/felix/lib/pretzel # recommended: LIBPATH=$(DESTDIR)/usr/lib/pretzel # directory for include files #INCLUDEDIR=/users/felix/lib/pretzel/include # recommended: INCLUDEDIR=$(DESTDIR)/usr/include/pretzel # target path for executables (platform dependent) #BINDIR1=/users/felix/bin # recommended: BINDIR1=$(DESTDIR)/usr/bin # target path for shell scripts (platform independent): #BINDIR2=/users/felix/bin # recommended: BINDIR2=$(DESTDIR)/usr/bin # target path for examples and documentation: #EXMDIR=/users/felix/lib/pretzel/doc # recommended: EXMDIR=$(DESTDIR)/usr/share/doc/pretzel/examples # target path for TeX style file: #TEXDIR=/users/felix/tex/inputs # recommended: TEXDIR=$(DESTDIR)/usr/share/texmf/tex/latex/pretzel # target path for manpages (pretzel.1 and pretzel-it.1) #MANPATH=/users/felix/lib/man/man1 # recommended: MANPATH=$(DESTDIR)/usr/share/man/man1 # ----------------------------------------------------------------- # do not change below here: # ----------------------------------------------------------------- # all - build executables all: lib doc (cd output; make release) (cd attr; make release) (cd ftokens; make regression release) (cd fgrammar; make regression release) (cd main; make regression release) (cd doc/styles; make pretzel-noweb.sty) (cd pretzel-it; make release) (cd contrib/noweb/general; make release) (cd languages/pascal/; make release) # lib - create the libpretzel.a library lib: alloca.c $(CC) -c alloca.c ar vrus libpretzel.a alloca.o # clean - remove intermediate products clean: (cd attr; make clean) (cd output; make clean) (cd ftokens; make clean) (cd fgrammar; make clean) (cd main; make clean) (cd contrib/noweb/general; make clean) (cd languages/pascal; make clean) # clobber - remove intermediate and final products clobber: clean (cd attr; make clobber) (cd output; make clobber) (cd ftokens; make clobber) (cd fgrammar; make clobber) (cd main; make clobber) (cd contrib/noweb/general; make clobber) (cd contrib/noweb/java.latex; make clobber) (cd languages/pascal; make clobber) rm -f libpretzel.a plainpp.o plaindpp.o nowebpretzelpp.o alloca.o rm -f include/* rm -f bin/* # install - copy files to places on system install: all cp libpretzel.a plainpp.o plaindpp.o $(LIBPATH) cp nowebpretzelpp.o $(LIBPATH) cp include/* $(INCLUDEDIR) cp bin/pretzel $(BINDIR1) # cp bin/pascalpp $(BINDIR1) cp bin/pretzel-it $(BINDIR2) # cp languages/pascal/pascal.ft languages/pascal/pascal.fg $(EXMDIR) cp doc/styles/pretzel-latex.sty $(TEXDIR) cp doc/styles/pretzel-noweb.sty $(TEXDIR) cp doc/styles/pretzeldoc.sty $(TEXDIR) cp man/pretzel.1 man/pretzel-it.1 $(MANPATH) # cp doc/pretzelbook/pretzelbook.dvi $(EXMDIR) # doc - make the documentation doc: # bundle - make a distribution bundle: echo "are you sure you dont want to make clobber first?" (cd .. ; \ tar -czv -X pretzel/files-to-exclude -f pretzel-$(VERSION).tar.gz pretzel/ ; \ mv pretzel-$(VERSION).tar.gz pretzel) # make a list of all files not to be included in the distribution # (for me only) exclude: (cd ..; \ find pretzel/ -print > /tmp/gaertner.files-to-exclude ; \ grep RCS /tmp/gaertner.files-to-exclude > pretzel/files-to-exclude; \ rm /tmp/gaertner.files-to-exclude ) # move the current distribution to the www directory (may change) www: mv pretzel-$(VERSION).tar.gz /users/wwwpub/Gaertner/pretzel/code # $Log: Makefile,v $ # Revision 1.9 1998/12/03 10:31:46 felix # *** empty log message *** # # Revision 1.8 1996/09/02 17:05:16 gaertner # hasty update for v.2.0b # # Revision 1.7 1995/09/08 16:29:57 gaertner # Added release of manpages to make install # # Revision 1.6 1995/09/08 16:18:17 gaertner # Uses gtar now. Didn't manage to exclude RCS files. # # Revision 1.5 1995/09/07 17:33:50 gaertner # Revised Makefile: targets all clean clobber install. Thanks to # Arno Schaefer for his help. # # Revision 1.5 1995/09/07 17:33:50 gaertner # Revised Makefile: targets all clean clobber install. Thanks to # Arno Schaefer for his help. # # Revision 1.4 1995/08/15 17:16:08 gaertner # Added alloca.c to the distribution. It's added to the library # now on installation. # # Revision 1.3 1995/04/27 07:51:59 gaertner # Added the COPYING file to the list that is bundled. # # Revision 1.2 1995/04/26 17:00:30 gaertner # Added rcs entries to file. # pretzel-2.0n-2/bin/0000755000000000000000000000000010765026553012634 5ustar rootrootpretzel-2.0n-2/README.debian0000644000000000000000000000017106537747543014177 0ustar rootrootpretzel for DEBIAN ------------------ [Nothing to add] Anthony Towns , Wed, 20 May 1998 18:59:40 +1000 pretzel-2.0n-2/diary0000644000000000000000000003167306651063115013123 0ustar rootroot -=*oOo*=- Diary of the `pretzel' Work for Release 2.0 -------------------- -=*oOo*=- Thu Mar 7 18:42:58 MEZ 1996: Started work on the new release. Tested the new implementation philosophy on the attribute class. This new philosophy includes: o use noweb instead of CWEB o use LaTeX2e instead of LaTeX o write specs and implementation into one noweb file and use the version.sty to seperate both. There will normally be two extra ``version'' environments inside a noweb file: bigspecs This included, you'll get a fully elaborate specification (with lots of examples). impls This included, the implementation will accompany the specification. I never thought to come back here. :-( Finished work on the attribute class today. Took V.1.5 of pretzel.sty and wrote a basic pretzeldoc.sty package for the documentation. Tue Mar 12 13:10:03 MET 1996 Started converting output.spc/.w to output.nw. Nearly finished. Wed Mar 13 12:34:32 MEZ 1996 Finished converting the Output class to noweb. Wrote a template file for own specializations and tested it with the new Ascii_terminal_output subclass. It seems to work. Thu Mar 14 11:04:52 MEZ 1996 Started rewriting the scanner for formatted token files. I'm trying to use flex's option to generate C++ scanner classes now. This will ease the use of multiple prettyprinters within one program. However one sentence in the flexdoc(1) man page makes my tummy ache: IMPORTANT: the present form of the scanning class is experimental and may change considerably between major releases. I've tried to keep the interface between the FlexLexer class and my own very small. I'm not using a subclass too, since this hides more information. Fri Mar 15 19:43:33 MEZ 1996 Worked hard on the generator for the prettyprinting scanner. Nearly got it to compile. Mon Mar 18 13:10:42 MEZ 1996 The generator for the prettyprinting scanner compiles. This stuff is getting hairy now. There are segmentation faults everywhere! Tue Mar 19 14:24:27 MEZ 1996 I'm on the edge: There's a funny `Internal error' when running ftokens. #0 0x10002ed0 in $PTRGL () warning: (Internal error: pc 0x10002ed0 in read in psymtab, but not in symtab.) I don't know what this is. The Output class outputs 1k of data to the screen and then dumps core. I'm on the edge of changing everything back to the normal C usage of flex. I'm changing everything back. Freezing the current version with name `cppflex'. Tue Mar 19 17:10:58 MEZ 1996 Finished all the changes, tested it and polished the files. That's enough for today. Wed Mar 20 12:40:33 MEZ 1996 Finished main part of transformation for the prettyprinting parser generation. Still need to get the generated output right. Asking Norman, how far his work has gone. Thu Mar 21 12:00:30 MEZ 1996 Finished final parts of the transformation. Tested pretzel and pretzel-it on simple examples. Need to test if two prettyprinters within a single program work too. Fri Mar 22 12:23:41 MEZ 1996 Finished first version of a simple prettyprinter for C. Fri Apr 12 12:05:37 MESZ 1996 Spent at least two weeks full time working on the noweb filter with Norman. The best thing to spring off from that project was an acceptable prettyprinting grammar for C. Today I started to prepare the formatted token files to contain code. There's a shift reduce conflict in the grammar now which I have to inspect. Mon Apr 22 11:19:08 MESZ 1996 Formatted grammar files can contain code now much in the style of formatted token files. Thu Apr 25 09:36:06 MESZ 1996 I haven't written much here on how the noweb filter is going on (and I don't want to put this info here anyway). Just a remark: Today I found the bug why the noweb filter spat out funny things when prettyprinting. I forgot to topp off the ostrstream with ``<< ends''. Fri Jun 7 18:04:57 MESZ 1996 Revised the homepage and WWW information. The current status of the project is: - still need to get a good prettyprinting grammar for C going - Joachim is working on the LaTeX macros - still need to port the stuff to gcc Package available via WWW now is v.2.0a. Scheduled start of work again: Mid July 1996. Mon Sep 2 18:23:55 MESZ 1996 Exams are harder than expected... So it's mid-july now?! Lee Wittenberg woke me up from sleeping on Pretzel and asked me for help. He had couldn't compile v.1.1 on Linux. His error had probably to do with the multiple flex scanner and Bison parser instances. Advised him to get newest version from Pretzel homepage. Ported everything to g++ (only alloca.c needs gcc). This is v.2.0b. Thu Sep 12 20:45:29 MESZ 1996 The ITI compiler seems to be very tolerant regarding multiple objects with the same name. Fixed the problem with multiple definitions of yylex and yyerror in the ftokens and fgrammar directory. The problem was that the parser (either in ftokens or fgrammar) called `a' yylex function, which should be the local yylex function supplied by myself. But there was another yylex function, namely the one produced by flex. Both were renamed using the same prefix (Pretzel_fg and Pretzel_ft) but they were still the two different functions with the same name. The ITI compiler seems to sort things like this out right. Also added the `extern "C"' declarations into ftscan.nw and fgscan.nw as proposed by Lee. Tested the compilation process on the HPs and the new Suns ober in 25. It compiles! This is v.2.0c. Fri Nov 1 15:17:14 MEZ 1996 First work on Pretzelbook. Wrote small example in languages/examples. Wed Nov 6 20:02:41 MEZ 1996 Continued work on Pretzelbook. First version runs through LaTeX now. Put Lee's Java prettyprinter in contrib/leew, but haven't had a chance of trying it. Fri Nov 8 19:55:22 MEZ 1996 Moved all the general noweb prettyprinter specific stuff from contrib/noweb/cee.latex to contrib/noweb/general. Now all files that a noweb prettyprinter needs are in this directory and necessary objects can be added to the pretzel library when you make release. Added -n option to pretzel-it, but haven't tested it. Also had a short look at Lee's Java stuff. Looks good. Will test it when new version of pretzel-it is ready. Thu Nov 14 19:58:37 MEZ 1996 The noweb option of pretzel-it works now. Cleaned up noweb directories and had a first go at Lee's Java prettyprinter. There's are some problems with ./totex though. Will continue later. Fri Nov 29 09:31:38 MEZ 1996 Got Icon. Released 2.0e because somebody in c.p.l wanted a Java prettyprinter for LaTeX. Mon Dec 2 11:45:01 MEZ 1996 Got the icon version of totex to work. Had a look at java.ft and java.fg. Started to write noweb sections of pretzelbook. Will press this thing now until christmas. Tue Dec 3 19:03:32 MEZ 1996 Started real work on the C grammar again. Have to sort out the TeX stuff soon. Lee's files are very helpful. Wed Dec 4 12:00:30 MEZ 1996 High Noon. Worked on the pretzel-noweb.sty but can't get the underscores to work right. Wrote part of Pretzelbook that explains adding C code to your rules. Spent too long on this. Wed Dec 4 18:32:04 MEZ 1996 Handled underscores through a small routine within the lexer. Can't make Pretzel handle empty chunks because I need the synopsis of C++ strstreams. Will look tomorrow. Thu Dec 5 10:11:40 MEZ 1996 The prettyprinting filter can handle empty chunks now. Tue Dec 10 20:05:52 MEZ 1996 Wrote chapter 1 of the Pretzelbook and revised chapter 2. Searched my files for some citations. They will make a good document. Wed Dec 11 12:16:17 MET 1996 Revised pretzel-it(1) manpage. Wed Dec 11 21:32:41 MEZ 1996 Tested the code that typesets context dependencies (i.e. typedefs). Pressed the C prettyprinting grammar to a state where I can continue. Added sections about this to the Pretzelbook. Thu Dec 12 12:18:48 MEZ 1996 The C grammar mangles loops and if constructs well now. Added sections of the Pretzelbook about frustrations while writing prettyprinting grammars. Mon Dec 16 09:39:30 MEZ 1996 Worked whole Sunday on Pretzelbook, hardly finished it. Mon Dec 16 12:06:48 MEZ 1996 Only future work and reference parts of Pretzelbook are missing. Manpages are in new format. Mon Dec 16 20:19:11 MEZ 1996 Everything ready to bundle and ship. Needs some slight package testing. Will do this tomorrow. This is 2.0f. Tue Dec 17 09:33:09 MEZ 1996 Version 2.0f is ready and available. Tue Dec 17 18:42:25 MEZ 1996 Updated WWW pages. Posted README. Tue Jul 8 21:03:08 MESZ 1997 This will be release 2.0g: New is a bug fix in output.nw proposed by Holger Uhr that allows correct cancelling of big_force format commands. Also new is the enhanced Java support for noweb (see contrib/noweb/java.latex). Bug fix in attribute_to_string function within the new Java prettyprinter. Wed Jul 9 12:30:40 MESZ 1997 Added Holger Uhr's version of java.fg (now called javahu.fg) into contrib/huhr. Updated the PretzelBook, which now is in it's second edition :-). Mon Feb 9 17:09:38 MEZ 1998 Added #define's of EXIT_SUCCESS and EXIT_FAILURE macros to all files that use them. This is due to problems by Denis Roegel in France, who seems to have an older system. This is 2.0h. Mon Feb 23 14:13:40 MEZ 1998 Started to try and get a noweb filter to use standard verbatim output if the prettyprinter fails to prettyprint code (files nowebpretzelpp.nw and pretty.nw needed a change). Also need to change the pretzel-noweb.sty too, do that tomorrow. Took up Colman Reilly's suggestion to add a ``ranlib'' to the relevant Makefiles that add stuff to the library libpretzel.a. Doing it by using ar -s. Tue Feb 24 16:33:37 MEZ 1998 Finished work on the verbatim feature of the noweb parser. This resulted in a change to the pretzel-noweb.sty, but it seems to work. This is Version 2.0i. Fri Mar 13 09:18:02 MEZ 1998 Updates manual pages to reflect changes in 2.0i, linked manpages and PretzelBook to the Pretzel Homepage (as suggested by Norman Ramsey). Sat Apr 25 10:04:58 MESZ 1998 Worked on pretzel-it script: now -d option produces the Bison .output file for a detailed analysis of the parser and its problems. Updated pretzel-it(1) manpage accordingly. Changed generated parser to do exectly one call of yyparse() which makes the semantics clearer. Added Michel Plugge's lx2l to contrib/plugge. Must add it to the pretzel-it script soon. Thu Jun 11 13:03:50 MET DST 1998 Moved development site to my ``own'' workstation (sun25.isa) now. Had to make some changes to the global Makefile. Updated WWW pages. Removed a bug introduced on April 25 which caused segmentation faults in prettyjava (replaced ``.'' by ``->'' in fgparse.nw). Thanks to David Wilson for the hint. This is 2.0j. Adjusted the distribution to suit debian standards as proposed by Anthony Towns. Added his GCL prettyprinter to contrib/aj. Places where the version number appear: README, pretzel-it.1, pretzel.1, Makefile. This is 2.0k. Thu Dec 3 12:19:27 MET 1998 Switched to new Linux machine pcd1. There are two seperate versions of the unpacked Pretzel distribution: one on the web server for surfing (which possibly is old), and one in my home (which is the primary version). Fixed a bootstrapping problem: making the first pascalpp prettyprinter in languages/pascal didn't work because it couldn't find pretzel-it and pretzel (weren't installed at that point). Fixed it through explicitly changing paths. Jason Alexander is trying to use Pretzel under Win95/NT. Because he doesn't have noweb I tangled all files and packed them together to form Version 2.0l This is not an official one. That's why I didn't change documentation. Wed Dec 16 12:16:40 MET 1998 It took me 8 hours to find the source of some peculiar misbehaviour (but I found it!). While experimenting with a Perl prettyprinter which mainly left the noweb verbatim output untouched, I discovered that newline command sequences vanished from behind chunks. This was due to my use of the strtok() function from string.h: this function cannot handle empty fields. Used strsep instead. Quote from strsep(3): The strsep() function was introduced as a replacement for strtok(), since the latter cannot handle empty fields. (However, strtok() conforms to ANSI-C and hence is more portable.) Had to recode the output loop in contrib/noweb/general/nowebpretzelpp.nw and introduced some wierd control structure which depends on shortcut expression evaluation. This is Version 2.0m Tue Jan 19 11:55:31 MET 1999 Denis B. Roegel points to two bugs that krept in through changes on Dec 3, 1998 and Dec 16, 1998: The bootstrapping code added to languages/pascal/Makefile was shell specific and so /bin/sh choked on the code. Fixed this through a bootstrapping copy of pretzel-it in that directory. The second bug was introduced through the use of strsep, which is not as portable as I hoped. Denis pointed me to a free implementation of strsep in the Lynx distribution 2.8.2 at http://www.slcc.edu/lynx/current and documented in http://www.slcc.edu/lynx/current/CHANGES. This is Version 2.0n. pretzel-2.0n-2/ftokens/0000755000000000000000000000000010765026553013535 5ustar rootrootpretzel-2.0n-2/ftokens/pascal.ft0000644000000000000000000000532406133473246015336 0ustar rootroot/* this is an example formatted token file for a pascal to test the * prettyprinting scanner generator. It was oiginally aimed to produce * TeX code to be formatted with the cwebmac package. */ %{ #define PSCAN_NAME pascan #define PSCAN_INIT_NAME pascan_init %} %% "<>" MATH { "$\\neq$" } // not equal sign "<=" MATH { "$\\leq$" } // less or equal ">=" MATH { "$\\geq$" } // greater or equal ":=" MATH { "\\hbox{${}\\mathrel{:=}{}$}" } // assignment '([^']|'')*' SIMP { "\\.{" + ** + "}" } // strings "(" OPEN ")" CLOSE [int i;] { [ in_table(yytext) ? create("it") : create("bf") ] } [ return(a[i\]); ] "[" OPEN "]" CLOSE "*" MATH { "$\\ast$" } "," MATH { ** + opt9 } ".." MATH "." SIMP ":" COLON ";" SEMI "=" MATH "+" MATH "-" MATH "<" MATH { "$<$" } ">" MATH { "$>$" } "/" MATH // this to allow underscores in identifiers: "_"[a-zA-Z0-9]* ID_TYPE {"\\" + ** } [0-9]+ SIMP [0-9]*"."[0-9]+ SIMP and MATH {"\\AND "} array ALPHA {"\\&{array}"} begin BEG {force + "\n" + "\\&{begin}" } boolean SIMP {"\\&{boolean}"} case CASE {force + "\\&{case}" + cancel } const INTRO {force + backup + "\\&{const}"} div MATH {" \\&{div} "} do OMEGA {"\\&{do}"} downto MATH {"\\&{downto}"} else ELSE {"\\&{else}" } end END {"\\&{end}" } for ALPHA {"\\&{for}" } function PROC {big_force + backup + "\\&{function} " } if ALPHA {"\\&{if}" } integer SIMP {"\\&{integer}"} mod MATH {"\\&{mod}"} not MATH {"\\neg "} of OMEGA {"\\&{of} " + cancel } or MATH {"\\V "} procedure PROC {big_force + backup + "\\&{procedure} " } program PROC {big_force + backup + "\\&{program} "} readln SIMP {"\\&{readln}"} real SIMP {"\\&{real}"} record RECORD {"\\&{record}"} repeat BEG {force + "\\&{repeat}" } then OMEGA {"\\&{then}" } to MATH {" \\&{to} "} type INTRO {force + backup + "\\&{type}" } until UNTIL {force + "\\&{until}" } var INTRO {force + backup + "\\&{var} " } while ALPHA {force + "\\&{while}" } with ALPHA {force + "\\&{with}"} write SIMP {"\\&{write}"} writeln SIMP {"\\&{writeln}"} "{"[^}]*"}" COMMENT { "\\hbox{$\\{$\\.{" + ** + "}$\\}$}" } // comments [a-zA-Z][a-zA-Z0-9]* ID_TYPE // identifiers [\t\ \n] // eat up whitespace . // eat up other non matching characters pretzel-2.0n-2/ftokens/index.list0000644000000000000000000000066406360671015015542 0ustar rootrootthis directory & prettyprinting scanner generator Makefile & the Makefile README & more information ftokens.nw & tester for this module (reads a .ft file from stdin and writes flex source to stdout) ftparse.nw & the specs and implementation of the generator of the prettyprinting scanner ftscan.nw & specs and implementation of scanner for .ft files pascal.ft & test input for regression test test.output.correct & correct test output pretzel-2.0n-2/ftokens/README0000644000000000000000000000116506123555627014422 0ustar rootrootSome hints to the files here: Makefile ftokens.nw tester for this module (reads a .ft file from stdin and writes flex source to stdout) ftparse.nw the specs and implementation of the generator of the prettyprinting scanner ftscan.nw specs and implementation of scanner for .ft files pascal.ft test input for regression test test.output.correct correct test output To get the header for the abstract base class of every prettyprinting scanner, type: make Pscan.h To get it for your generated scanner class, type: make Ppscan.h (note the double `p'). Look into the big specs of ftparse.nw for details. pretzel-2.0n-2/ftokens/ftparse.nw0000644000000000000000000010746710765025173015563 0ustar rootroot% This is a file written using noweb % % $Id: ftparse.nw,v 1.7 1996/09/17 13:45:01 gaertner Exp $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} \includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification %\excludeversion{impls}% without implementation \title{A Generator for the Prettyprinting Scanner} \author{Felix G\"artner} \maketitle \begin{abstract} This file describes the interface \begin{impls}and implementation\end{impls} of a new \CPP\ class that can be used to build a prettyprinting scanner from a formatted token file. A formatted token file is a file containing a description of ``formatted tokens'' for prettyprinting a certain programming language. It is used within the framework of the ``pretzel'' project. Pretzel is a universal prettyprinter generator. \end{abstract} \tableofcontents \section{Introduction} A {\em prettyprinting scanner} is a scanner that not only returns a token code for the next token from the input but also returns an indication ({\em attribute}) of how this token is to be prettyprinted. Thus a prettyprinting scanner doesn't merely return simple tokens, but {\em formatted tokens}. Such a scanner is a prerequisite for a {\em prettyprinting parser}, that in turn takes the formatted tokens and puts them together according to a {\em formatted grammar}, i.e.~a grammar that is enhanced with formatting rules. Such a parser can be regarded as a normal prettyprinter. This file describes the interface of a new \CPP\ class that can be used to generate such a prettyprinting scanner from rules that are specified in a file, the so called {\em formatted token file}. About the precise format of this file confer the main documentation of the ``pretzel'' project, of which this program is a part. I will assume that you know this format (or at least have seen an example file) and that you are familiar with the prettyprinting method that is used by all components. The program of concern here is the actual generator for the prettyprinting scanner. @ This is an overview of the header file for the new class. <

>= #ifndef FTPARSE_H #define FTPARSE_H <
> <> #endif @ \begin{impls} The implementation of this class will be done using the standard \UNIX\ tool Bison, which is a parser generator. The idea is to parse the formatted token file and convert it into a valid flex file, from which a scanner then can be build (using flex of course). So here's the frame of the Bison file. <>= %{ #include #include "ftparse.h" #include %} <> %% <> %% <> @ \end{impls} \section{Interface (Overview)} The thing of interest here is the generator for the prettyprinting scanner. The generator is a new \CPP\ class called [[Pscan_builder]]. It has a single member function called [[build]] which does all the work of building. It takes two arguments: % \begin{enumerate} \item The first one is a pointer to an input stream where it expects to read the formatted token file from. \item The second one is a pointer to an output stream, where it writes the generated code to. \end{enumerate} % The function returns an integer value to indicate if everything worked well (0) or if an error occured (1). For a description on how the generated prettyprinting scanner looks, see section \ref{sec:scannerinterface} on page \pageref{sec:scannerinterface} below. There are two more functions for error diagnosis. The first is called [[error_text]] which returns a more elaborate description of why the [[build]] function might have returned a 1 as a string. The second is called [[error_line]] which returns the line of the input file where this error has occured. The [[debug_on]] and [[debug_off]] functions allow to watch the generation process in details. <>= class Pscan_builder { public: Pscan_builder(); ~Pscan_builder(); int build(istream*, ostream*); // for error diagnosis and debugging: char* error_text(); int error_line(); void debug_on(); // write what the generator is doing to cerr void debug_off(); private: <> }; @ These are the header files needed. <
>= #include @ \section{Interface (Details)} In this section I will present a complete reference of the new [[Pscan_builder]] class\begin{impls} together with it's implementation\end{impls}. \begin{impls} \subsection{Ideas behind the Implementation} The idea behind the implementation is to use bison to generate a parser and do the translation from formatted token file to flex file on the fly whilst parsing. The format of the formatted token file is so similar to a flex file, that this is possible. The parser will use the new scanner class [[Ftscanner]] described in the document {\tt ftscan.nw}. By default bison generates a global parser function [[yyparse]]. We want to shield this and all the other globals within the new class. So we declare the parser to be pure and redefine the prefixes of the globals using the {\tt -p} command line option of bison. We'll use the same prefix as used in generating the scanner (``[[Pretzel_ft]]''). <>= %pure_parser %{ #include "ftscan.h" /* include scanner */ %} @ The scanner function expected by [[yyparse]] is called [[Pretzel_ftscan]] if we use the {\tt -p} option. But actually it's a member function of the scanner class [[Ftscanner]]. How deal with this problem? We'll define a private member of the [[Pscan_builder]] class to hold an instance of the scanner class and use this to scan the input file. <>= Ftscanner* scanner; @ We'll also need to include the specification for this class then. <
>= #include "ftscan.h" @ So a call to the scanner is like calling the [[scan]] member function of the [[scanner]] itself. We need a way to simply trick bison into using [[scanner->scan]] everytime it wants to call [[Pretzel_ftlex]]. This is more difficult than it seems, because [[yyparse]] will be called from inside a member function with no idea what scanner object to use. We'll get around this problem by using a static variable again for communication. It will always hold a pointer to the current scanner to be used by [[yyparse]]. This is not very nice but necessary, since bison doesn't allow us to redefine the interface to [[yyparse]] at all. This means that the [[build]] member function will work well with multiple instances of the [[Pscan_builder]] class, but {\em will not be reentrant}. (See also page \pageref{yyparseinterface2} for another problem concerning the interface of [[yyparse]].) \label{yyparseinterface1} <>= %{ static Ftscanner* static_scanner = NULL; %} @ So every time Bison calls [[yylex]], it should call the following small dummy function. It is declared static so that multiple parser instances don't get upset. Also, since there is a second definition of a [[yylex]]-type function in the scanner implementation file, we must take care that we don't get multiple versions of the same function in the linked code. That's why we have to [[#undef]] the [[yylex]] definition that is automatically inserted into the code when we use the [[-P]]-option. Also, a few macros have to be redefined to take care that this static version of [[yylex]] is the only one declared. <>= static int yylex(Attribute* *rval) { return(static_scanner->scan(rval)); } @ Some versions of Bison (the newer ones) have a [[YYLEX_DECL]] macro that can be used to declare [[yylex]]. We'll declare it ourself and make sure it isn't declared again. <>= %{ /* make sure yylex is declared with name ``yylex'' */ #undef yylex static int yylex(Attribute* *rvalue); /* make sure that it's only declared once */ #define YYLEX_DECL %} @ The semantic value of the tokens manipulated within bison are simple strings that are joint together while parsing. Joining together strings in the right way will result in a giant string, which is the valid flex file, when the parsing has finished. As we don't want to get into any hassle copying strings from one place to another, we'll use the [[Attribute]] class to do this. We won't use the [[Format_attributes]] though, but only the [[Text_attributes]]. They weren't written for this task, but they are certainly good candidates to be used. <>= %{ #include "attr.h" #define YYSTYPE Attribute* %} @ So now, when parsing the formatted token file and generating the flex file, the parser will finally arrive at the end of its work and have a huge attribute that contains the contents of the flex file. Now what? Well, we can't output it to the output stream specified in the [[build]] function, since there is no way to tell [[yyparse]] what output stream to take. Also, we can't use a private member of the builder to hold this attribute temporaily, because the [[yyparse]] function doesn't have access to it, even if we declare it friend to the builder class. (This is because the [[yyparse]] function has no means of knowing, which object it was invoked by.) So the best thing to do is to store this huge attribute in a static variable called [[rest]] and output it later, when [[yyparse]] has retuned. (See also page \pageref{yyparseinterface} for another problem concerning the interface of [[yyparse]].) \label{yyparseinterface2} <>= %{ static Attribute* rest = NULL; %} @ A static variable within this module will hold the current text describing the error message encountered. Normally this will be a syntax error and this is the default entry. But while parsing, we might be able to specify more precisely what's gone wrong. In such cases we simply assign a new text to this variable. <>= %{ static char* error_message = "syntax error"; %} @ To be able to debug the grammar, I've put in the [[debug_on]] and [[debug_off]] member functions into the class. They'll simply switch on (and off) the bison debugging mechanism. The semantic values of the tokens will be output to [[cerr]] too, and so we need to include the header of the [[Output]] class too. <>= %{ #define YYDEBUG 1 #include "output.h" %} @ \end{impls} \subsection{Creating and Destroying the Generator} The constructor and destructor of the [[Pscan_builder]] class do nothing much. They simply have to be there before you call [[build]]. \begin{impls} The implementation is straightforward too. <>= Pscan_builder::Pscan_builder() { scanner = NULL; }; Pscan_builder::~Pscan_builder() { if (scanner != NULL) delete scanner; }; @ \end{impls} \subsection{Activation and Results of the Generator} \label{sec:scannerinterface} The actual work is performed when you call [[build]]. It takes a pointer to an input stream [[is]] and a pointer to an output stream [[os]]. It then starts to read a formatted token file from [[is]] and outputs code for the prettyprinting scanner to [[os]]. The resulting code is flex code that contains the complete definition of a new \CPP\ prettyprinting scanner class. This new class is a subclass of an abstract base class [[Pscan]], that offers one virtual function [[scan]] that is redefined within the newly generated subclass. The exact interface can be found in the file {\tt Pscan.h}. It is: \label{pretscanspecs} <>= #include #include"attr.h" class Pscan { public: Pscan(istream*) {}; ~Pscan() {}; virtual int scan(Attribute**) = 0; }; @ The interface of the generated prettyprinting scanner is: <>= class PSCAN_NAME : public Pscan { public: PSCAN_NAME(istream*); ~PSCAN_NAME(); int scan(Attribute**); }; @ The name of the generated class is [[PSCAN_NAME]] by default and has to be redefined using preprocessor macros, such as for example % \begin{quote} [[#define PSCAN_NAME Pscan_for_pascal]] \end{quote} % By default the name of the derived subclass will be [[Ppscan]]. A header file containing the abstract base class would look like this: <
>= #ifndef PSCAN_H #define PSCAN_H <> #endif @ A header file containing the derived scanner class could look like this (by default the header file is called {\tt Ppscan.h}). Note that there is no precaution against double inclusion. <
>= /* header file for a prettyprinting scanner */ /* NB: This file is NOT protected against double inclusion! */ #include "Pscan.h" // include abstract base class #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #endif <> @ \begin{impls} The implementation of the [[build]] function is possibly the trickiest thing in this entire class. It uses the internal [[Ftscanner]] class object and then calls [[yyparse]]. The assignment [[static_scanner = scanner]] before calling [[yyparse]] ensures that the right scanner is used. (See also page \pageref{yyparseinterface1} for a description of this problem.) We'll have to use a nonstandard [[Output]] for outputting the file contents, as the abstract base class can't be used. You can use any output subclass that doesn't upset the strings (and [[Latex_cweb_output]] is a good candidate for this, especially because it comes free with the abstract base class). <>= int Pscan_builder::build(istream* is, ostream* os) { scanner = new Ftscanner(is); assert(scanner != NULL); <> static_scanner = scanner; int ret_val = yyparse(); if (ret_val != 0) { return(1); } else { Latex_cweb_output tmp_output(*os); // create an output for [[os]] rest->print(tmp_output); // and print the contents there. return(0); } } @ To ensure that the resulting flex code gets right, a lot of declarations and additional \CPP\ code have to be added to the file. This is done by declaring some additional strings that get appended to the front and back of the flex file when it is produced. These additional lines essentially contain the rest of the \CPP\ implementation of the interface specified above. There are three static variables holding text: \begin{itemize} \item [[initial_lines]] will hold text that is put to the very beginning of the resulting flex file. \item [[before_lines]] will hold text that is put just before the \verb+%%+ line that starts the rules part of the flex file. \item [[after_lines]] will be put behind a second \verb+%%+ line and will contain additional \CPP\ code. \end{itemize} The corresponding integer variables will be used to turn these string arrays into [[Attribute]]s, which in turn are held in the corresponding attribute variables. <>= %{ static char *initial_lines[] = { "/************************************************\n", " * This is a flex file generated by pretzel *\n", " * *\n", " ************************************************/\n\n", <> "\n" }; static char *before_lines[] = { "/************************************************\n", " * some pretzel definitions start here: *\n", " ***********************************************/\n\n", <> "\n" }; static char *after_lines[] = { "/************************************************\n", " * additional pretzel C code follows here: *\n", " ***********************************************/\n", <> "/************************************************\n", " * additional user defined C code follows here: *\n", " ***********************************************/\n", "\n" }; static const int initial = sizeof(initial_lines)/sizeof(initial_lines[0]); static const int before = sizeof(before_lines)/sizeof(before_lines[0]); static const int after = sizeof(after_lines)/sizeof(after_lines[0]); static Attribute *initial_text = create(null); static Attribute *before_text = create(null); static Attribute *after_text = create(null); %} @ All these lines are accumulated into the three static variables and are inserted into the file within the grammar specified in section \ref{sec:grammarrules} on page \pageref{sec:grammarrules}. Using the constants like [[after]] spares us from counting the line numbers every time we change the text. Thanks to Andreas Kirschbaum for suggesting this hack. <>= int i=0; for (i=0; i>= "%{ \n\n", " /* some needed headers: */ \n", "#include \n", "#include\"attr.h\" \n\n", " /* we'll define yywrap() which is needed for the scanner\n", " * here, so we won't have to bother about it if we're \n", " * doing the standard case. You can define your own version\n", " * by #undef'ing PSCAN_YYWRAP and supplying your own definition\n", " * in the definitions section. \n", " */ \n", "#define PSCAN_YYWRAP \n\n", " /* input will come from this istream */ \n", "static istream * yyin_stream; \n\n", " /* redefine YYINPUT to read from input streams */ \n", "#undef YY_INPUT \n", "#define YY_INPUT(buf, result, max_size) { \\\n", " if (yyin_stream->eof()) result=YY_NULL; \\\n", " else { \\\n", " yyin_stream->read(buf, max_size); \\\n", " result=yyin_stream->gcount(); \\\n", " } \\\n", "} \n\n", "%} \n\n", @ Within the [[before_lines]] we have to put everything that can be redefined by the user and has to be mentioned before the body of [[yylex]] comes along. <>= "%{ \n\n", " /* the default name of the include file with the token\n", " * code definitions is stored in PTOKDEFS_NAME and \n", " * defaults to `ptokdefs'. \n", " */ \n", "#ifndef PTOKDEFS_NAME \n", "#define PTOKDEFS_NAME \"ptokdefs.h\" \n", "#endif \n\n", " /* now we have to include the token definitions */ \n", "#include PTOKDEFS_NAME \n\n", " /* allow user to choose generated scanner class name*/\n", "#ifndef PSCAN_NAME \n", "#define PSCAN_NAME Ppscan \n", "#include \"Ppscan.h\" \n", "#endif \n\n", " /* redefine the interface of the scanner */ \n", "#undef YY_DECL \n", "#define YY_DECL int yylex (Attribute**rvalue) \n\n", " /* here's the standard version of yywrap() */ \n", "#ifdef PSCAN_YYWRAP \n", "extern \"C\" int yywrap() { \n", " return(1); \n", "} \n", "#endif \n\n", "%} \n\n", @ The [[after_lines]] contain the rest of the definition of the implemented class. <>= "PSCAN_NAME::PSCAN_NAME (istream* is ) : Pscan(is)\n", "{ \n", " yyin_stream = is; \n", "} \n", "int PSCAN_NAME::scan(Attribute* *rvalue) \n", "{ \n", " return(yylex(rvalue)); \n", "} \n", "PSCAN_NAME::~PSCAN_NAME () \n", "{ \n", " yyrestart(NULL); \n", "} \n", @ \end{impls} \subsection{Error Diagnosis and Debugging} The error diagnosis functions can be used, if the [[build]] function has returned an error code (1). Calling [[error_text]] will result in a more elaborate explanation of the error cause (mostly ``syntax error'') and [[error_line]] will reveal the line number of the formatted token file, where the generator choked. \begin{impls} The implementation is straighforward again. The [[error_text]] function simply returns the internal error message and the [[error_line]] function askes the scanner and returns its line value. <>= char *Pscan_builder::error_text() { return(error_message); } int Pscan_builder::error_line() { return(scanner->line()); } @ The debugging member functions \ldots % XXX \end{impls} \begin{impls} \section{Bison Implementation of the Generator} \label{sec:grammarrules} This section contains the complete bison rules for the generator function [[yyparse]]. It is the main part of the implementation. All this was written for GNU bison version 1.19. \subsection{Token Declarations} Bison will expect the scanner to return the following tokens: <>= %token REGEXPR %token ID %token STRING %token FMTCMD %token TEXT %token A_LINE %token PERCENT_PERCENT %token UNKNOWN %token BEG_CODE %token CODE %token END_CODE @ \subsection{The Grammar Rules} Now we'll go through the grammar rules one by one in a top down fashion. A formatted token file consists of lots of top lines, a final top line (which is `\verb+%%+') and a list of definitions possibly followed by again a `\verb+%%+' line and another row of lines. If we want to insert stuff into the definitions section of the output, we have to do this between [[$1]] and [[$2]] of the [[join]] command below. The [[preflex_file]] is the final token to which everything should be reduced. So we save the semantic value of this final token in the [[contents]] member function of the generator class. <>= preflex_file : lines PERCENT_PERCENT def_list { rest=$$=join(initial_text,$1, before_text,$2,$3, create("\n%%\n"),after_text);} | lines PERCENT_PERCENT def_list PERCENT_PERCENT lines { rest=$$=join(initial_text,$1, before_text,$2,$3,$4,after_text,$5);} ; lines : /* empty */ {rest=$$=create(null);} | lines A_LINE {rest=$$=join($1,$2);} ; @ A definition list collects definitions of formatted grammar rules. A definition always starts with a regular expression. Definitions can have an empty body. This is good for specifying rules for example to eat up whitespace. They will come out like this in the output file: \begin{quote} {\it regular-expression} \hspace{1cm} \verb+/* empty */+ \end{quote} <>= def_list : /* empty */ {rest=$$=create("\n");} | def_list def { rest=$$=join($1,$2,create("\n"));} ; def : REGEXPR { rest=$$=join( create("\n"), $1, create("\t\t/* empty */\n") );} ; @ The next case sees a regular expression with a token name following it but no attribute definition. Here we need the default mechanism. The generated line in the output file will look like this: % \begin{quote} {\it regular-expression}\hspace{1cm}[[{*rvalue=create(yytext);return(ID);}]] \end{quote} <>= def : REGEXPR ID { rest=$$=join( create("\n"), $1, create("\t\t{*rvalue=create(yytext);return ("), $2, create(");}\n") );} ; @ Of course you can influence the attribute by stating an attribute definition after the token code. From version 2.0 of pretzel onwards we'll have to deal with code fragments within the attribute definition as well. This will be a little tricky. We'll allow the user to explicitly state starting code (which is inserted before the attribute is built) and ending code (which is put behind the attribute building process but before the final [[return]]). Code within attribute definitions is expected to be an [[Attribute*]] and can thus be handled as if it were a string for format command. Conventions: Starting code and ending code are writte outside of the attribute definition. Any one of the three things (starting code, attribute definition, ending code) can be omitted. The simple case that sees none of them has been handled above. Here are the more complex cases. To enhance readability of the output file, every created attribute is put onto a new line and indented a little to the right. Also note, that the [[join]] function is only called with two parameters at most. This should be fixed soon. Code will be put onto lines by itself and indented to make sure it follows flex conventions. So you will have something like this in the output file: % \begin{verbatim} REGEXPR { ...possible starting code... *rvalue=join( ...translated attribute definition... ); ...possible ending code... return(ID);} \end{verbatim} % We'll start off by saying, what [[code]] is. Code is encircled by [[BEG_CODE]] and [[END_CODE]] delimiters which are stripped off in the output file. Code lines following code are indented a little. <>= code : BEG_CODE code_lines END_CODE { rest=$$=$2; } ; code_lines : CODE { rest=$$=$1; } | code_lines CODE { rest=$$=join($1, create("\t\t\t"), $2); } ; opt_code : code { rest=$$=$1; } | /* empty */ { rest=$$=create(null); } ; @ In the rules for definitions, we might have optional code before the attribute definition or behind it. have to look out for code. Starting and ending code are optional code. Lookout here that we don't use [[join]] with more arguments than allowed. <>= def : REGEXPR ID opt_code '{' attr_def '}' opt_code { rest=$$=join( create("\n"), $1, create("\t\t{"), $3, create(" *rvalue="), $5, create("\n\t\t"), join( $7, create(" return("), $2, create(");}\n")) );} ; @ Here is the case for subsequent definitions joined together with the `\verb+|+' sign. A common error is to use lowercase in the token identifiers. This is tried to fight here. <>= def : REGEXPR '|' def { rest=$$=join(create("\n"),$1,create("\t\t"),$2,$3);} | REGEXPR UNKNOWN { error_message = "illegal identifier (USE UPPERCASE)"; return(3); } ; @ An attribute definition is enclosed by curled brackets that have been spotted already above. As the `[[*rvalue=]]' part too has already been generated above, we only need to produce a `[[join]]' stuff here. <>= attr_def : attr_list {rest=$$=join(create("join(\n\t\t\t"), $1, create(");\n\t\t\t") );} ; attr_list : attr {rest=$$=$1;} ; @ Here we ensure that only instances of join will be called with at most two arguments. We'll also allow to omit the [[+]]. This is an enhancement of Pretzel version 2.0. <>= attr_list : attr_list '+' attr {rest=$$=join( create("join(\n\t\t\t\t"), $1, create(",\n\t\t\t\t"), $3, create("\n\t\t\t)") );} | attr_list attr {rest=$$=join( create("join(\n\t\t\t\t"), $1, create(",\n\t\t\t\t"), $2, create("\n\t\t\t)") );} ; @ Finally we say, what an [[attr]] actually is. From version 2.0 of \pretzel{} we also allow code to be an attribute. <>= attr : STRING {rest=$$=join(create("create("), $1,create(")"));} | FMTCMD {rest=$$=join(create("create("), $1,create(")"));} | TEXT {rest=$$=create("create(yytext)");} | code {rest=$$=$1;} | UNKNOWN {error_message = "illegal attribute"; return(2);} ; @ \section{Additional bison Functions} Here's the definition of the [[yyerror]] routine needed by the generated parser. It isn't supplied automatically, so we have to cater for it. We don't want to output any bison error messages so we simply return 0. Its name has to contain the same prefix as specified on the bison command line. <>= int Pretzel_fterror (const char *s) { return 0; } @ This line is needed so that Bison doesn't declare the supposed [[yyerror]] routine extern. <>= %{ int Pretzel_fterror (const char *s); #define YYERROR_DECL %} @ \end{impls} \begin{bigspecs} \section{Examples} This section contains some examples of how to use the [[Pscan]] class and subclasses. \subsection{A simple and standard example} Here's an example for a formatted token file for a normal (default) prettyprinting scanner. It's an example that can be used to prettyprint simple equations using \TeX's math mode. <>= ALPH [a-zA-Z] ALPHNUM [a-zA-Z0-9] NUM [0-9] %% {ALPH}{ALPHNUM}* ID { "\\hbox{" + ** + "}" } {NUM}+ NUMBER "+" PLUS "-" MINUS "/" DIV "*" MULT { "\\cdot" } "=" EQUAL @ If you run this file through the generator, you'll get a class called [[Ppscan]] that looks like this: <>= class Ppscan : public Pscan { Ppscan(istream*); ~Ppscan(); int scan(Attribute**); }; @ The header file for this class is in the file {\tt Ppscan.h}. So to use the scanner, your program should look something like this: \begin{verbatim} /* program using my new prettyprinting scanner */ #include"Ppscan.h" int main() { ... Ppscan mypscanner(&cin); Attribute* look; int tokval; ... while ( (tokval = mypscanner.scan(look)) != 0 ) { ... /* do something with it */ } ... return(0); } \end{verbatim} \subsection{A more complex example} Say, you are using multiple scanners in your program. You'll need to rename different instances of the generated scanner class to be able to do so. For example, you want to have two scanner classes, one for \C\ and one for \PASCAL{}. Let's look at one of them, the one for \PASCAL. We want to call the class [[Pascalpscanner]]. To rename the class, you have to put a [[#define]] into the formatted token file. <>= %{ /* redefine name of generated scanner class */ #define PSCAN_NAME Pascalpscanner %} ALPH [a-zA-Z] ALPHNUM [a-zA-Z0-9] %% {ALPH}{ALPHNUM}* ID // more token definitions follow ... @ Now you'll get a subclass that looks like this: <>= class Pascalpscanner : public Pscan { Pascalpscanner(istream*); ~Pascalpscanner(); int scan(Attribute**); }; @ You'll have to rename the header file {\tt Ppscan.h} into something like {\tt Pascalpscan.h}. It is important that the [[#define]] is issued {\em before} you include the header file in your program that uses the scanner. So it should look something like this: \begin{verbatim} /* program using the new Pascal prettyprinting scanner */ #define PSCAN_NAME Pascalpscanner #include"Pascalpscan.h" int main() { ... Pascalpscanner pscanner(&cin); ... /* etc. */ \end{verbatim} Of course it could be better to change the name of the scanner class right inside the file {\tt Pascalpscanner} itself. This would get rid of the nasty [[#define]]. But this is one possibility you can choose from. \end{bigspecs} \end{document} % % $Log: ftparse.nw,v $ % Revision 1.7 1996/09/17 13:45:01 gaertner % Added the `extern "C"' to the generated scanner too. % % Revision 1.6 1996/09/12 18:42:44 gaertner % Refined declaration handling of yylex and yyerror. Now it % works on sun and HP. % % Revision 1.5 1996/09/12 17:58:24 gaertner % Changed yylex to static, so that it won't magle with the % other global yylex. It seems that the ITI compiler fixes this % on the fly! % % Revision 1.4 1996/04/12 15:30:31 gaertner % Caters for code fragments within attribute definitions now. % % Revision 1.3 1996/04/12 08:26:48 gaertner % Allowed to omit the `+' in attribute definitions. % % Revision 1.2 1996/03/21 11:02:27 gaertner % Added empty implementation of constructor and destructor of % abstract base class Pscan. % Added an #include line for the scanner to the generated output. % Added call :Pscan(is) to constructor of Ppscan. % % Revision 1.1 1996/03/19 16:02:41 gaertner % Initial revision % % pretzel-2.0n-2/ftokens/ftokens.nw0000644000000000000000000000311010765025131015536 0ustar rootroot% This is a file written using noweb % % $Id: ftokens.nw,v 2.0 1996/12/16 17:31:57 gaertner Exp $ % \documentclass{article} \usepackage{a4,version,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{A Tester for the Prettyprinting Scanner Generator} \author{Felix G\"artner} \maketitle \begin{abstract} This document describes a short program to test the new [[Pscan_builder]] class used to generate prettyprinting scanners from formatted token files. \end{abstract} \tableofcontents \section{The Tester} It's a simple program that uses a [[Pscan_builder]] object to process standard input into standard output. Invoke this program like this: % \begin{quote} {\tt ftokens} < {\it formatted-token-file} \end{quote} % and look whether the output makes sense. <>= #include #include #include #include using namespace std; #include"ftparse.h" //extern int yydebug; int main(int argc, char** argv) { int i; //yydebug=1; Pscan_builder generator; i = generator.build(&cin, &cout); if (i!=0) { cerr << argv[0] << ": " << generator.error_text() << " in line " << generator.error_line() << endl; } return(0); } @ \end{document} % % $Log: ftokens.nw,v $ % Revision 2.0 1996/12/16 17:31:57 gaertner % *** empty log message *** % % Revision 1.1 1996/03/19 15:56:40 gaertner % Initial revision % % Revision 1.1 1996/03/19 15:56:40 gaertner % Initial revision % % pretzel-2.0n-2/ftokens/index.html0000644000000000000000000000246706360671021015533 0ustar rootroot Index file for directory "pretzel/ftokens" of Pretzel distribution

Index file for directory "pretzel/ftokens" of Pretzel distribution

Files and directories are:

this directory

    prettyprinting scanner generator
Makefile
    the Makefile
README
    more information
ftokens.nw
    tester for this module (reads a .ft file from stdin and writes flex source to stdout)
ftparse.nw
    the specs and implementation of the generator of the prettyprinting scanner
ftscan.nw
    specs and implementation of scanner for .ft files
pascal.ft
    test input for regression test
test.output.correct
    correct test output

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 13:12:18 MESZ 1997 pretzel-2.0n-2/ftokens/ftscan.nw0000644000000000000000000004534610765025211015363 0ustar rootroot% This is a file written using noweb % % $Id: ftscan.nw,v 1.6 1996/09/12 18:44:56 gaertner Exp $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{A Scanner for Formatted Token Files} \author{Felix G\"artner} \maketitle \begin{abstract} This document describes the interface \begin{impls}and implementation\end{impls} of a scanner for formatted token files. A formatted token file is a file containing a description of ``formatted tokens'' for prettyprinting a certain programming language. It is used within the framework of the ``pretzel'' project. Pretzel is a universal prettyprinter generator. \end{abstract} \tableofcontents \section{Introduction} A {\em prettyprinting scanner} is a scanner that not only returns a token code for the next token from the input but also returns an indication ({\em attribute}) of how this token is to be prettyprinted. Thus a prettyprinting scanner doesn't merely return simple tokens, but {\em formatted tokens}. Such a scanner is a prerequisite for a {\em prettyprinting parser}, that in turn takes the formatted tokens and puts them together according to a {\em formatted grammar}, i.e.~a grammar that is enhanced with formatting rules. Such a parser can be regarded as a normal prettyprinter. This file describes the interface \begin{impls}and flex implementation\end{impls} of a new \CPP\ class used to generate such a prettyprinting scanner from rules that are specified in a file, the so called {\em formatted token file}. About the precise format of this file confer the main documentation of the ``pretzel'' project, of which this program is a part. I will assume that you know this format (or at least have seen an example file) and that you are familiar with the prettyprinting method that is used by all components. Here's an overview of the frame of the header file: <

>= #ifndef FTSCAN_H #define FTSCAN_H <
> <> #endif @ \begin{impls} The implementation will use the flex scanner generator (installed on the development site is version 2.4.6). We won't use the feature of flex to create a \CPP\ scanner class, because we want to stick with stuff that has been tested and that will probably work. A flex file has the following frame. <>= %{ #include"ftscan.h" /* include own header */ %} <> %% <> %% <> @ \end{impls} \section{Interface (Overview)} This section describes the interface of the scanner that scans formatted token files. Formatted token files contain token definitions and descriptions of associated attributes for a prettyprinter. This scanner is used by a parser that checks the syntax of a given formatted token file. There are basicly three things you have and want to do with the scanner: \begin{itemize} \item Create a new scanner and initialize it to tell it where to take the input characters from. \item Call it, to know, which token is next in the input stream (this is called ({\em scanning}). \item Destroy the scanner explicitly (to free memory, clean up or whatever). \end{itemize} Here's the declaration of the new scanner class. <>= class Ftscanner { public: Ftscanner(istream*); /* create and initialize new scanner */ ~Ftscanner(); /* remove a scanner */ int scan(Attribute**); /* scan for a new token */ int line(); /* returns line number of last token scanned */ <> }; @ The function [[line]] is an additional member function aimed to help debugging. The formatted look of a newly scanned token is returned by a call by reference argument from the [[Attribute]] class. See the {\tt attr.nw} file for a description of this class. Anyway, we have to include these headers. <
>= #include"attr.h" /* the Attribute class */ #include @ \section{Interface (Details)} In this section I will present every member function of the new scanner class in a detailed fashing for a complete reference\begin{impls} and will explain the ideas and details behind the implementation\end{impls}. \begin{impls} A scanner generated by flex is mainly a function called [[yylex]] that scans from a given [[FILE*]] and returns token codes as integers. We'll use this function to scan the formatted token file and to return an additional string with the token code that describe the token in more detail and can be used to piece together the target file implementing the prettyprinting scanner. We'll use the [[Attribute]] class fo this purpose. (Though it wasn't designed for it, we can still use it here.) We also have to redefine the interface for [[yylex]] to suit these requirements. <>= %{ #undef YY_DECL #define YY_DECL int yylex(Attribute* *rvalue) %} @ By default, the name of the scanner function is [[yylex]]. By specifying the {\tt -P} option at the command line you can redefine the ``yy'' prefix and thus change the name of the scanner function. The implementation expects that the scanner is generated using the option ``{tt -PPretzel_ft}'' and thus will expect the scanner function to be called: % \begin{quote} [[Pretzel_ftlex]] \end{quote} \end{impls} A short word about using multiple scanners within one program: Because of drawbacks of the underlying algorithm \begin{impls}(the interface of flex)\end{impls} the resulting scanner is not reentrant and using multiple instances of the scanner class in the same program will be extremely hazardrous. This might seem a severe drawback, but isn't too bad in the end, because it was built to be used in only one instance. \begin{impls}This is also the reason why I shouldn't have used a class to implement it, but the interface was designed before learning about flex' deficiencies.\end{impls} \begin{impls} Because of the above note, we'll use static variables instead of private members to handle the private information of the class. <>= /* none */ @ We want the scanner to read from an input stream and not from a [[FILE*]], so we have to take care about this. We'll define a static variable that holds the [[istream]] object pointer and will be used by the scanner. <>= %{ static istream* yyin_stream; %} @ Also, we have to modify the way, in which [[yylex]] reads it's data. This is done by redefining the [[YY_INPUT]] macro. Thanks to Christine Detig for the hint. <>= %{ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } %} @ The current line number has to be stored somewhere too. This is done within the static variable [[line]]. <>= %{ static int line_number = 1; %} @ \end{impls} \subsection{Creating and Initializing a new Scanner} Here's the constructor of the class [[Ftscanner]]. It takes a pointer to an input stream (\CPP\ [[istream]] object) as argument and reset the scanner's internals. \begin{impls} The implementation of the constructor is pretty easy. It simply stores the given input stream pointer and resets the line number count. The line number is initially set to 1 since we have no line 0. <>= Ftscanner::Ftscanner(istream* is) { line_number = 1; yyin_stream = is; } @ \end{impls} \subsection{Destroying a Scanner} The [[~Ftscanner]] simply destroys the specified scanner again. \begin{impls} This is implemented by resetting the internal scanner in case we want to scan a new formatted token file. Note that although the scanner object dissappears, the internal scanner state still is valid. <>= Ftscanner::~Ftscanner() { yyrestart(NULL); } @ \end{impls} \subsection{Scanning} The next function is the normal scanner member function called [[scan]]. It returns token codes as integer values together with the corresponding attribute (as a call by reference argument). Table \ref{tab:returnvalues} shows all the possible values that [[scan]] might return. They are partly defined as \C\ macros, and partly simply the character values of the given symbols. The macros are defined in a header file that is generated by the parser for formatted token files (the file {\tt ftokdefs.h}). See the specifications in {\tt ftparse.nw} for details. \begin{impls} The implementation has to include this header file. <>= %{ #include "ftokdefs.h" %} @ \end{impls} From version 2.0 of \pretzel{} onwards it is allowed to put C code into attribute definitions. The `new' tokens [[BEG_CODE]], [[CODE]] and [[END_CODE]] reflect this change. It contains a line of code (possibly followed by more) to be inserted into the attribute definition. \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{ll} symbolic name & meaning \\ \hline [[{]] & opening curly bracket \\ [[}]] & closing curling bracket \\ [[+]] & a `plus' sign \\ [[|]] & a vertical line \\ [[REGEXPR]] & a regular expression \\ [[ID]] & an identifier \\ [[STRING]] & a string \\ [[FMTCMD]] & a format command \\ [[TEXT]] & the `[[**]]' symbol \\ [[BEG_CODE]] & starting code delimiter in attribute definitions \\ [[CODE]] & a line of code in attribute definitions \\ [[END_CODE]] & ending code delimiter in attribute definitions \\ [[A_LINE]] & a line of text (code, etc.) \\ [[PERCENT_PERCENT]] & the `[[%%]]' line \\ [[UNKNOWN]] & a token that couldn't be matched \\ \end{tabular} \caption{(symbolic) return values of [[scan]] member function.} \label{tab:returnvalues} \end{center} \end{table} Basicly a formatted token file cosists of a `limbo' of \C\ code that is followed by a line containing `\verb+%%+'. After that come a long series of formatted token definitions that basicly consist of a regular expression, a symbolic name for this token and an optional formatting instruction for this token. I'll have a short example ready below. The [[scan]] member function has a call by reference argument of type [[Attribute*]] to return the semantic value of the token, whose token code is returned as return value. \begin{impls} The [[scan]] member function is a delayed call to [[yylex]]. <>= int Ftscanner::scan(Attribute* *rvalue) { return(yylex(rvalue)); } @ The exact behaviour, i.e.~a complete specification of the flex regular expressions can be found in section \ref{sec:flexbody} on page \pageref{sec:flexbody}. \end{impls} \subsection{Debugging} There is an additional member function that can be used for debugging purposes. The value of [[line()]] returns the line number that the token was in that was last returned. \begin{impls} Looking at the implementation we have to note that the internal variable has to be incremented every time we scan a newline in the input file. This has to be checked in the definitions of section \ref{sec:flexbody} and is a possible bug source! <>= int Ftscanner::line() { return(line_number); } @ \end{impls} \begin{impls} \section{The flex Token descriptions} \label{sec:flexbody} This section contains the complete flex implementation of the scanner class. Note that we have to increment the current line number every time we encounter and scan a newline. The really important things in the formatted token file are the lines inbetween the \verb+%%+ tokens (or between the first and the end of the file if no user code is given). So we'll have the scanner ignore everything from the beginning of the file up to the first two percents and then start it's real work. We'll distinguish between these two states using an exclusive start condition [[R]] (for ``rules''). <>= %x R @ Now lets have a look on how the scanner reads the top lines and gets into this start condition. When the scanner finds the first `\verb+%%+', he'll return a [[PERCENT_PERCENT]] token and switch into ``rules'' mode. Until he finds such a line, he'll keep on returning the prelude of the file line by line. <>= ^"%%"\n { *rvalue=create(yytext); BEGIN(R); line_number++; return(PERCENT_PERCENT); } /* Otherwise we simply return one line at a time */ .*\n { *rvalue=create(yytext); line_number++; return A_LINE; } @ So, assume that we're in `rules mode', we'll have to look out for unindented regular expressions, token identifiers and attribute definitions. <>= /* The following regular expression is a regular expression * for regular expressions! */ ^(([^ \t\n])|(\\\ ))+ *rvalue=create(yytext); return REGEXPR; /* scan an identifier (only uppercase allowed */ [A-Z][A-Z0-9_]* *rvalue=create(yytext); return ID; @ Now for the attribute definitions. They consist of a series of strings and formatting instructions within curled brackets. Additionally, there might be the code delimiters enclosing one or more code lines. Because code is somewhat more difficult to scan as formatted token files, we'll introduce a new start condition [[AC]] for ``attribute code''. It's exclusive too. <>= %x AC @ Here are the things we might encounter. <>= "{" *rvalue=create(yytext); return yytext[0]; "}" *rvalue=create(yytext); return yytext[0]; "[" *rvalue=NULL; BEGIN(AC); return BEG_CODE; @ Before we continue, a short thought: Say, we've seen an opening code delimiter and we're in [[AC]] mode. Now all lines must be returned up to the point where we find a matching closing delimiter. Closing delimiters (usually an angled bracket) must be escaped if they are used within the code. The escape character is stripped off when the string is returned using the [[unescaped]] function. <>= (([^\]\n])|(\\\]))* *rvalue=create(unescaped(yytext)); return CODE; (([^\]\n])|(\\\]))*\n *rvalue=create(unescaped(yytext)); line_number++; return CODE; "]" *rvalue=NULL; BEGIN(R); return END_CODE; @ The [[unescaped]] function removes backslashes from a given string if they are followed by a closing delimiter (currently a `{\tt ]}'). The string length shrinks by the number of backslashes removed. [It's declared [[static]] because an identical function occurs in the file {\tt fgscan.nw}. A better solution would be to add it to the pretzel library.] The implementation has two pointers into the array. The first points to the position where the next unescaped character should be placed, the second one holds the position of the next character to be inspected. We only shorten the given string. That's why we don't [[malloc]] storage and work on a copy. <>= %{ static char* unescaped(char* s) { int left = 0; /* next position to place [[s[right]]] */ int right = 0; while (s[right] != 0) { // should be `!= NULL', shouldn,t it, but // some compilers choke on it if ((s[right] == '\\') && (s[right+1] == ']')) { right++; } s[left] = s[right]; left++; right++; } s[left] = s[right]; /* terminate string */ return(s); } %} @ Here's what else we can expect in attribute definitions. <>= \"[^\"]*\" *rvalue=create(yytext); return STRING; "+" *rvalue=create(yytext); return yytext[0]; "**" *rvalue=create("yytext"); return TEXT; null | indent | outdent | opt0 | opt1 | opt2 | opt3 | opt4 | opt5 | opt6 | opt7 | opt8 | opt9 | backup | break_space | force | big_force | no_indent | cancel *rvalue=create(yytext); return FMTCMD; @ We'll allow the following abbreviations: <>= bsp *rvalue=create("break_space"); return FMTCMD; b_force *rvalue=create("big_force"); return FMTCMD; @ Tokens with the same ID and attribute definition may be concatenated by a vertical line. <>= "|" *rvalue=create(yytext); return yytext[0]; @ Here are a few extras. We'll eat up whitespace, but are carefull enough to increment the line number. Also, we can simply ignore the comments. <>= [\ \t] /* eat up whitespace */ \n line_number++; "//".* /* ignore comments */ @ To finish the rules and allow the user to add some code at the end of the file, this is the rule to get out of the `rules mode' again. <>= ^"%%"\n { *rvalue=create(yytext); BEGIN(INITIAL); line_number++; return PERCENT_PERCENT; } @ In case we meet something that we can't match, we'll return an [[UNKNOWN]] token. <>= . return(UNKNOWN); @ \section{Additional flex functions} This section contains the definition of the [[yywrap]] function needed to complete a flex scanner. Returning 1 means that the scanner can exit when receiving an end of file indication. The [[extern "C"]] is due to Lee Wittenberg. It gets around a linkage error with some versions of gcc. <>= %{ extern "C" int yywrap() { return(1); } %} @ \end{impls} \end{document} % % $Log: ftscan.nw,v $ % Revision 1.6 1996/09/12 18:44:56 gaertner % Added extern "C" (thanks Lee). % % Revision 1.5 1996/09/02 16:02:48 gaertner % Changed the initialization routines and fixed `unescaped' to work % with g++ % % Revision 1.4 1996/04/12 15:29:45 gaertner % Caters for code fragments within attribute definitions. % % Revision 1.3 1996/03/19 15:55:38 gaertner % Tested and working version using new interface. % % Revision 1.3 1996/03/19 15:55:38 gaertner % Tested and working version using new interface. % % Revision 1.2 1996/03/19 13:28:23 gaertner % Version using the -+ option of flex to produce the scanner. Seems to % upset the Output class (see diary). Saving it so I might change back % to it again. % % Revision 1.1 1996/03/18 09:02:13 gaertner % Initial revision % % pretzel-2.0n-2/ftokens/Makefile0000644000000000000000000001617406537744605015215 0ustar rootroot# $Id: Makefile,v 1.12 1996/09/12 18:42:11 gaertner Exp $ # ---------------------------------------------------------------------- # # Makefile for the formatted token file scanner and parser # # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = g++ # de-comment this if you want a debug version: #DBVERSION = -D XXX # flags : CFLAGS = -g -I../include -L.. -lpretzel # prefix for globals of scanner and parser (`yy' by default) GLOBALSPREFIX = Pretzel_ft # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # You probably don't need to change anything from here: # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # Groups of files: # all noweb sources NOWEBS = ftscan.nw ftparse.nw ftokens.nw # root chunk name of headers HEADERCHUNK = header # root chunk name of C implementation IMPLEMENTATIONCHUNK = implementation # root chunk name of flex implementation FLEXIMPLCHUNK = flex-implementation # root chunk name of bison implementation BISONIMPLCHUNK = bison-implementation # all `WEB' sources (old) #WEBS = ftokens.w ftparse.spc ftparse.y ftscan.spc ftscan.l # all other program WEB sources (old) #ETCWEBS = pscan.spc # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = Makefile pascal.ft test.output.correct README # name of the distribution package DISTNAME = # Which program to make by default: PROG = ftokens # objects of this program: OBJS = ftokens.o ftparse.o ftscan.o # objects to be released: RELOBJS = ftparse.o ftscan.o # C sources of this program: CSRCES = ftokens.c ftparse.c ftscan.c # intermediate products from which C sources are made INTERMEDIATES = ftscan.l ftparse.y # stuff to be deleted when cleaning up: OTHERCRAP = ftparse.aux ftparse.dvi ftparse.idx ftparse.log \ ftparse.scn ftparse.tex ftparse.toc \ ftscan.aux ftscan.dvi ftscan.idx ftscan.log \ ftscan.scn ftscan.tex ftscan.toc \ ftscan.l ftparse.y \ pscan.dvi pscan.idx pscan.log pscan.scn \ pscan.tex pscan.toc \ Pscan.h Ppscan.h \ ftokens.aux ftokens.dvi ftokens.idx ftokens.log \ ftokens.scn ftokens.tex test.output # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = ftparse.h ftscan.h ftokdefs.h Pscan.h Ppscan.h # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) # these are all header files produced from WEBs that may appear ALLHEADERS = $(HEADERS) # these are all the executables that could be produced ALLPROGS = ftokens # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle NOTANGLE= notangle NOWEAVE = noweave TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = tex-it latex # ---------------------------------------------------------------------- BISONOPTIONS = -p$(GLOBALSPREFIX) FLEXOPTIONS = -L -P$(GLOBALSPREFIX) # ---------------------------------------------------------------------- .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h # overall rules: .nw.tex: $(NOWEAVE) -delay $*.nw > $*.tex .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .nw.h: $(NOTANGLE) -L -R$(HEADERCHUNK) $*.nw > $*.h .nw.c: $(NOTANGLE) -L -R$(IMPLEMENTATIONCHUNK) $*.nw > $*.c .nw.l: $(NOTANGLE) -R$(FLEXIMPLCHUNK) $*.nw > $*.l .nw.y: $(NOTANGLE) -R$(BISONIMPLCHUNK) $*.nw > $*.y .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) -c $*.c $(CCFLAGS) .y.c: $(YACC) $(BISONOPTIONS) $*.y mv $*.tab.c $*.c .l.c: $(LEX) -t $(FLEXOPTIONS) $*.l > $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) $(CC) -o $@ $(OBJECTS) $(CCFLAGS) $(OBJS): $(HEADERS) $(CSRCES) $(CSRCES): $(INTERMEDIATES) # make the common token header ftokdefs.h: ftparse.y $(YACC) -d ftparse.y mv ftparse.tab.h ftokdefs.h Ppscan.h: ftparse.nw $(NOTANGLE) -R"header file for prettyprinting scanner" ftparse.nw >Ppscan.h Pscan.h: ftparse.nw $(NOTANGLE) -R"header file for abstract base class of [[Pscan]]" ftparse.nw >Pscan.h # regression: regression: $(PROG) ./ftokens test.output if diff test.output test.output.correct; \ then echo "Regression test is fine."; \ else echo "Regression test failed."; \ fi # list all source code: print: # apply lint to all C sources: lint: # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(OTHERCRAP) # remove everything that doesn't belong to original source: clobber: clean $(REMOVE) $(ALLPROGS) # bundle source files together into an archive: #bundle: # tar cf $(DISTNAME).tar \ # $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # copy executables into PATH directories, et al. install: # release a new version: release: $(HEADERS) $(RELOBJS) cp $(HEADERS) ../include ar vrus ../libpretzel.a $(RELOBJS) # ====================================================================== # # $Log: Makefile,v $ # Revision 1.12 1996/09/12 18:42:11 gaertner # Changed to g++. # # Revision 1.11 1996/03/19 16:04:49 gaertner # Tailored for the new noweb versions of the files. # # Revision 1.11 1996/03/19 16:04:49 gaertner # Tailored for the new noweb versions of the files. # # Revision 1.10 1996/03/15 13:39:12 gaertner # Check in before switching to noweb. # # Revision 1.9 1995/08/15 17:20:11 gaertner # Moved options of CC to the end of the command line for portability. # # Revision 1.9 1995/08/15 17:20:11 gaertner # Moved options of CC to the end of the command line for portability. # # Revision 1.8 1995/08/15 17:03:30 gaertner # Added possibility to change the global prefix of scanner and # parser variables. # # Revision 1.7 1995/04/26 18:06:46 gaertner # You can now make a regression test. # Compiling/releasing use lpretzel library. # Making .dvi's will use LaTeX. Invoke TeX manually if you want to # get a printout of the pscan.spc file. # # Revision 1.6 1994/10/31 19:03:27 gaertner # Now make bundle creates ftokens.tar # # Revision 1.5 1994/10/24 16:49:48 gaertner # now the ftokens.o object isn't released anymore. # # Revision 1.4 1994/10/24 16:30:29 gaertner # Added pscan.spc that is also released. # # Revision 1.3 1994/10/18 10:58:30 gaertner # Flex doesn't run in debug mode anymore. # # Revision 1.2 1994/10/14 15:54:38 gaertner # Initial revision of granny version using the Makefile # template. # # pretzel-2.0n-2/ftokens/test.output.correct0000644000000000000000000002205310765025232017431 0ustar rootroot/************************************************ * This is a flex file generated by pretzel * * * ************************************************/ %{ /* some needed headers: */ #include #include"attr.h" /* we'll define yywrap() which is needed for the scanner * here, so we won't have to bother about it if we're * doing the standard case. You can define your own version * by #undef'ing PSCAN_YYWRAP and supplying your own definition * in the definitions section. */ #define PSCAN_YYWRAP /* input will come from this istream */ static istream * yyin_stream; /* redefine YYINPUT to read from input streams */ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } %} /* this is an example formatted token file for a pascal to test the * prettyprinting scanner generator. It was oiginally aimed to produce * TeX code to be formatted with the cwebmac package. */ %{ #define PSCAN_NAME pascan #define PSCAN_INIT_NAME pascan_init %} /************************************************ * some pretzel definitions start here: * ***********************************************/ %{ /* the default name of the include file with the token * code definitions is stored in PTOKDEFS_NAME and * defaults to `ptokdefs'. */ #ifndef PTOKDEFS_NAME #define PTOKDEFS_NAME "ptokdefs.h" #endif /* now we have to include the token definitions */ #include PTOKDEFS_NAME /* allow user to choose generated scanner class name*/ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* redefine the interface of the scanner */ #undef YY_DECL #define YY_DECL int yylex (Attribute**rvalue) /* here's the standard version of yywrap() */ #ifdef PSCAN_YYWRAP extern "C" int yywrap() { return(1); } #endif %} %% "<>" { *rvalue=join( create("$\\neq$")); return(MATH);} "<=" { *rvalue=join( create("$\\leq$")); return(MATH);} ">=" { *rvalue=join( create("$\\geq$")); return(MATH);} ":=" { *rvalue=join( create("\\hbox{${}\\mathrel{:=}{}$}")); return(MATH);} '([^']|'')*' { *rvalue=join( join( join( create("\\.{"), create(yytext) ), create("}") )); return(SIMP);} "(" {*rvalue=create(yytext);return (OPEN);} ")" {int i; *rvalue=join( in_table(yytext) ? create("it") : create("bf") ); return(a[i]); return(CLOSE);} "[" {*rvalue=create(yytext);return (OPEN);} "]" {*rvalue=create(yytext);return (CLOSE);} "*" { *rvalue=join( create("$\\ast$")); return(MATH);} "," { *rvalue=join( join( create(yytext), create(opt9) )); return(MATH);} ".." {*rvalue=create(yytext);return (MATH);} "." {*rvalue=create(yytext);return (SIMP);} ":" {*rvalue=create(yytext);return (COLON);} ";" {*rvalue=create(yytext);return (SEMI);} "=" {*rvalue=create(yytext);return (MATH);} "+" {*rvalue=create(yytext);return (MATH);} "-" {*rvalue=create(yytext);return (MATH);} "<" { *rvalue=join( create("$<$")); return(MATH);} ">" { *rvalue=join( create("$>$")); return(MATH);} "/" {*rvalue=create(yytext);return (MATH);} "_"[a-zA-Z0-9]* { *rvalue=join( join( create("\\"), create(yytext) )); return(ID_TYPE);} [0-9]+ {*rvalue=create(yytext);return (SIMP);} [0-9]*"."[0-9]+ {*rvalue=create(yytext);return (SIMP);} and { *rvalue=join( create("\\AND ")); return(MATH);} array { *rvalue=join( create("\\&{array}")); return(ALPHA);} begin { *rvalue=join( join( join( create(force), create("\n") ), create("\\&{begin}") )); return(BEG);} boolean { *rvalue=join( create("\\&{boolean}")); return(SIMP);} case { *rvalue=join( join( join( create(force), create("\\&{case}") ), create(cancel) )); return(CASE);} const { *rvalue=join( join( join( create(force), create(backup) ), create("\\&{const}") )); return(INTRO);} div { *rvalue=join( create(" \\&{div} ")); return(MATH);} do { *rvalue=join( create("\\&{do}")); return(OMEGA);} downto { *rvalue=join( create("\\&{downto}")); return(MATH);} else { *rvalue=join( create("\\&{else}")); return(ELSE);} end { *rvalue=join( create("\\&{end}")); return(END);} for { *rvalue=join( create("\\&{for}")); return(ALPHA);} function { *rvalue=join( join( join( create(big_force), create(backup) ), create("\\&{function} ") )); return(PROC);} if { *rvalue=join( create("\\&{if}")); return(ALPHA);} integer { *rvalue=join( create("\\&{integer}")); return(SIMP);} mod { *rvalue=join( create("\\&{mod}")); return(MATH);} not { *rvalue=join( create("\\neg ")); return(MATH);} of { *rvalue=join( join( create("\\&{of} "), create(cancel) )); return(OMEGA);} or { *rvalue=join( create("\\V ")); return(MATH);} procedure { *rvalue=join( join( join( create(big_force), create(backup) ), create("\\&{procedure} ") )); return(PROC);} program { *rvalue=join( join( join( create(big_force), create(backup) ), create("\\&{program} ") )); return(PROC);} readln { *rvalue=join( create("\\&{readln}")); return(SIMP);} real { *rvalue=join( create("\\&{real}")); return(SIMP);} record { *rvalue=join( create("\\&{record}")); return(RECORD);} repeat { *rvalue=join( join( create(force), create("\\&{repeat}") )); return(BEG);} then { *rvalue=join( create("\\&{then}")); return(OMEGA);} to { *rvalue=join( create(" \\&{to} ")); return(MATH);} type { *rvalue=join( join( join( create(force), create(backup) ), create("\\&{type}") )); return(INTRO);} until { *rvalue=join( join( create(force), create("\\&{until}") )); return(UNTIL);} var { *rvalue=join( join( join( create(force), create(backup) ), create("\\&{var} ") )); return(INTRO);} while { *rvalue=join( join( create(force), create("\\&{while}") )); return(ALPHA);} with { *rvalue=join( join( create(force), create("\\&{with}") )); return(ALPHA);} write { *rvalue=join( create("\\&{write}")); return(SIMP);} writeln { *rvalue=join( create("\\&{writeln}")); return(SIMP);} "{"[^}]*"}" { *rvalue=join( join( join( create("\\hbox{$\\{$\\.{"), create(yytext) ), create("}$\\}$}") )); return(COMMENT);} [a-zA-Z][a-zA-Z0-9]* {*rvalue=create(yytext);return (ID_TYPE);} [\t\ \n] /* empty */ . /* empty */ %% /************************************************ * additional pretzel C code follows here: * ***********************************************/ PSCAN_NAME::PSCAN_NAME (istream* is ) : Pscan(is) { yyin_stream = is; } PSCAN_NAME::scan(Attribute* *rvalue) { return(yylex(rvalue)); } PSCAN_NAME::~PSCAN_NAME () { yyrestart(NULL); } /************************************************ * additional user defined C code follows here: * ***********************************************/ pretzel-2.0n-2/COPYING0000644000000000000000000004307605747646162013141 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pretzel-2.0n-2/fgrammar/0000755000000000000000000000000010765026553013660 5ustar rootrootpretzel-2.0n-2/fgrammar/fgrammar.nw0000644000000000000000000000264510765025043016022 0ustar rootroot% This is a file written using noweb % % $Id: fgrammar.nw,v 1.1 1996/03/21 08:13:57 gaertner Exp gaertner $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{A Tester for the prettyprinting parser generator} \author{Felix G\"artner} \maketitle \begin{abstract} This document describes a short program to test the new [[Pparse_builder]] class used to generate prettyprinting parsers from formatted grammar files. \end{abstract} \tableofcontents \section{The Tester} It's a simple program that uses a [[Pparse_builder]] object to process standard input into standard output. Invoke this program like this: % \begin{quote} {\tt fgrammar} < {\it formatted-token-file} \end{quote} % and look whether the output makes sense. <>= #include #include #include using namespace std; #include"fgparse.h" int main(int argc, char** argv) { int i; Pparse_builder generator; //yydebug=1; i = generator.build(&cin, &cout); if (i!=0) { cerr << argv[0] << ": " << generator.error_text() << " at line " << generator.error_line() << endl; } return(0); } @ \end{document} % % $Log: fgrammar.nw,v $ % Revision 1.1 1996/03/21 08:13:57 gaertner % Initial revision % % pretzel-2.0n-2/fgrammar/fgparse.nw0000644000000000000000000011150110111701037015632 0ustar rootroot% This is a file written using noweb % % $Id: fgparse.nw,v 1.8 1998/06/11 10:59:14 felix Exp $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{A Generator for the Prettyprinting Parser} \author{Felix G\"artner} \maketitle \begin{abstract} This file describes the interface \begin{impls}and implementation\end{impls} of a new \CPP\ class that can be used to build a prettyprinting parser from a formatted grammar file. A formatted grammar file is a file containing a context free grammar which is enhanced by additional formatting information. The prettyprinting parser constitutes the main part of a prettyprinter for the language specified by the formatted grammar. This file is used within the framework of the ``pretzel'' project. Pretzel is a universal prettyprinter generator. \end{abstract} \tableofcontents \section{Introduction} A {\em prettyprinting parser} is a parser that does prettyprinting as a result of parsing. Such a parser normally uses an attribute grammar, i.e.~every token has an associated attribute. These attributes specify how the token looks. An attribute grammar that contains such prettyprinting information will be called a {\em formatted grammar}. Together with information about the formatting of terminal tokens (so called {\em formatted tokens}) a formatted grammar defines a prettyprinter. The ``pretzel'' project aims to generate such a prettyprinter automatically from a formatted token and formatted grammar description laid down in files of a special format. These files are called the {\em formatted token file} and the {\em formatted grammar file}. The precise format of these files can be obtained by reading the main documentation of the pretzel project. I will assume that you know about this and also about the prettyprinting method that the generated prettyprinter uses. @ This document describes the interface of a new \CPP\ class that generates a prettyprinting parser from a formatted grammar file. This is an overview over the frame the header file: <
>= #ifndef FGPARSE_H #define FGPARSE_H <
> <> #endif @ \begin{impls} The implementation of this class will be done using the standard \UNIX\ tool bison, which is a parser generator. The idea is to parse the formatted token file and convert it into a valid bison file, from which a parser then can be build (using bison of course). So here's the frame of the bison file. <>= %{ #include #include "fgparse.h" /* include own header */ #include #include %} <> %% <> %% <> @ \end{impls} \section{Interface (Overview)} The thing of interest here is the generator for the prettyprinting parser. The generator is a new \CPP\ class called [[Pparse_builder]]. It has a single member function called [[build]] which does all the work of building. It takes two arguments: % \begin{enumerate} \item The first one is a pointer to an input stream where it expects to read the formatted token file from. \item The second one is a pointer to an output stream, where it writes the generated code to. \end{enumerate} % The function returns an integer value to indicate if everything worked well (0) or if an error occured (1). For a description on how the generated prettyprinting scanner looks, see section \ref{sec:parserinterface} on page \pageref{sec:parserinterface} below. There are two more functions for error diagnosis. The first is called [[error_text]] which returns a more elaborate description of why the [[build]] function might have returned a 1 as a string. The second is called [[error_line]] which returns the line of the input file where this error has occured. The [[debug_on]] and [[debug_off]] functions allow to watch the generation process in details. <>= class Pparse_builder { public: Pparse_builder(); ~Pparse_builder(); int build(istream*, ostream*); // for error diagnosis and debugging: char* error_text(); int error_line(); void debug_on(); // write what the generator is doing to cerr void debug_off(); private: <> }; @ These are the header files needed. <
>= #include @ \section{Interface (Details)} In this section I will present a complete reference of the new [[Pparse_builder]] class\begin{impls} together with it's implementation\end{impls}. \begin{impls} \subsection{Ideas behind the Implementation} The idea behind the implementation is to use bison to generate a parser and do the translation from formatted grammar file to bison file on the fly whilst parsing. The format of the formatted grammar file is so similar to a bison file, that this is possible. The parser will use the new scanner class [[Fgscanner]] described in the document {\tt fgscan.nw}. By default bison generates a global parser function [[yyparse]]. We want to shield this and all the other globals within the new class. So we declare the parser to be pure and redefine the prefixes of the globals using the {\tt -p} command line option of bison. We'll use the same prefix as used in generating the scanner (``[[Pretzel_fg]]''). <>= %pure_parser %{ #include "fgscan.h" /* include scanner */ %} @ The scanner function expected by [[yyparse]] is called [[Pretzel_ftscan]] if we use the {\tt -p} option. But actually it's a member function of the scanner class [[Fgscanner]]. How deal with this problem? We'll define a private member of the [[Pparse_builder]] class to hold an instance of the scanner class and use this to scan the input file. <>= Fgscanner* scanner; @ We'll also need to include the specification for this class then. <
>= #include "fgscan.h" @ So a call to the scanner is like calling the [[scan]] member function of the [[scanner]] itself. We need a way to simply trick bison into using [[scanner->scan]] everytime it wants to call [[Pretzel_ftlex]]. This is more difficult than it seems, because [[yyparse]] will be called from inside a member function with no idea what scanner object to use. We'll get around this problem by using a static variable again for communication. It will always hold a pointer to the current scanner to be used by [[yyparse]]. This is not very nice but necessary, since bison doesn't allow us to redefine the interface to [[yyparse]] at all. This means that the [[build]] member function will work well with multiple instances of the [[Pparse_builder]] class, but {\em will not be reentrant}. (See also page \pageref{yyparseinterface2} for another problem concerning the interface of [[yyparse]].) \label{yyparseinterface1} <>= %{ static Fgscanner* static_scanner = NULL; %} @ a So when Bison calls [[yylex]] it should actually call the following small function. It's static, so that it won't upset other Bison parsers around, but we have to undefine any macro definition of [[yylex]] (such as those introduced when using the [[-P]] option). Also, we define the [[YYLEX_DECL]] macro so that it is declared okay. <>= static int yylex(Attribute* *rval) { return(static_scanner->scan(rval)); } @ Some versions of Bison (the newer ones) have a [[YYLEX_DECL]] macro that can be used to declare [[yylex]]. We'll declare it ourself and make sure it isn't declared again. <>= %{ /* make sure yylex is declared with name ``yylex'' */ #undef yylex static int yylex(Attribute* *rvalue); /* make sure that it's only declared once */ #define YYLEX_DECL %} @ The semantic value of the tokens manipulated within bison are simple strings that are joint together while parsing. Joining together strings in the right way will result in a giant string, which is the valid bison file, when the parsing has finished. As we don't want to get into any hassle copying strings from one place to another, we'll use the [[Attribute]] class to do this. We won't use the [[Format_attributes]] though, but only the [[Text_attributes]]. They weren't written for this task, but they are certainly good candidates to be used. <>= %{ #include "attr.h" #define YYSTYPE Attribute* %} @ So now, when parsing the formatted token file and generating the flex file, the parser will finally arrive at the end of its work and have a huge attribute that contains the contents of the flex file. Now what? Well, we can't output it to the output stream specified in the [[build]] function, since there is no way to tell [[yyparse]] what output stream to take. Also, we can't use a private member of the builder to hold this attribute temporaily, because the [[yyparse]] function doesn't have access to it, even if we declare it friend to the builder class. (This is because the [[yyparse]] function has no means of knowing, which object it was invoked by.) So the best thing to do is to store this huge attribute in a static variable called [[rest]] and output it later, when [[yyparse]] has retuned. (See also page \pageref{yyparseinterface} for another problem concerning the interface of [[yyparse]].) \label{yyparseinterface2} <>= %{ static Attribute* rest = NULL; %} @ A static variable within this module will hold the current text describing the error message encountered. Normally this will be a syntax error and this is the default entry. But while parsing, we might be able to specify more precisely what's gone wrong. In such cases we simply assign a new text to this variable. <>= %{ static char* error_message = "syntax error"; %} @ To be able to debug the grammar, I've put in the [[debug_on]] and [[debug_off]] member functions into the class. They'll simply switch on (and off) the bison debugging mechanism. The semantic values of the tokens will be output to [[cerr]] too, and so we need to include the header of the [[Output]] class too. <>= %{ #define YYDEBUG 1 #include "output.h" %} @ \end{impls} \subsection{Creating and Destroying the Generator} The constructor and destructor of the [[Pparse_builder]] class do nothing much. They simply have to be there before you call [[build]]. \begin{impls} The implementation is straightforward too. <>= Pparse_builder::Pparse_builder() { scanner = NULL; }; Pparse_builder::~Pparse_builder() { if (scanner != NULL) delete scanner; }; @ \end{impls} \subsection{Activation and Results of the Generator} \label{sec:parserinterface} The actual work is performed when you call [[build]]. It takes a pointer to an input stream [[is]] and a pointer to an output stream [[os]]. It then starts to read a formatted grammar file from [[is]] and outputs code for the prettyprinting parser to [[os]]. The resulting code is bison code that contains the complete definition of a new \CPP\ prettyprinting parser class. This new class is a subclass of an abstract base class [[Pparse]], that offers one virtual function [[prettyprint]] that is redefined within the newly generated subclass. The exact interface of the generated prettyprinter class can be found in the file {\tt Pparse.h}. It is: \label{pretparsespecs} <>= #include #include"attr.h" #include"output.h" class Pparse { public: Pparse() {}; virtual ~Pparse() {}; virtual int prettyprint(istream*, ostream*) = 0; virtual int prettyprint(istream*, Output*) = 0; }; @ The interface of the generated prettyprinter is: <>= class PPARSE_NAME : public Pparse { public: PPARSE_NAME(); ~PPARSE_NAME(); int prettyprint(istream*, ostream*); int prettyprint(istream*, Output*); void debug_on(); void debug_off(); }; @ The name of the generated class is [[PPARSE_NAME]] by default and has to be redefined using preprocessor macros, such as for example % \begin{quote} [[#define PPARSE_NAME Prettyprinter_for_pascal]] \end{quote} % By default the name of the derived subclass will be [[Ppparse]] (note the three `p's). A header file containing the abstract base class would look like this: <
>= #ifndef PPARSE_H #define PPARSE_H <> #endif @ A header file containing the derived parser class could look like this (by default the header file is called {\tt Ppparse.h}). Note that there is no precaution against double inclusion. <
>= /* header file for a prettyprinting parser */ /* NB: This file is NOT protected against double inclusion! */ #include "Pparse.h" // include abstract base class #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif <> @ \begin{impls} The implementation of the [[build]] function is possibly the trickiest thing in this entire class. It uses the internal [[Fgscanner]] class object and then calls [[yyparse]]. The assignment [[static_scanner = scanner]] before calling [[yyparse]] ensures that the right scanner is used. (See also page \pageref{yyparseinterface1} for a description of this problem.) We'll have to use a nonstandard [[Output]] for outputting the file contents, as the abstract base class can't be used. You can use any output subclass that doesn't upset the strings (and [[Latex_cweb_output]] is a good candidate for this, especially because it comes free with the abstract base class). <>= int Pparse_builder::build(istream* is, ostream* os) { scanner = new Fgscanner(is); assert(scanner != NULL); <> static_scanner = scanner; int ret_val = yyparse(); if (ret_val != 0) { return(1); } else { Latex_cweb_output tmp_output(*os); // create an output for [[os]] rest->print(tmp_output); // and print the contents there. return(0); } } @ To ensure that the resulting bison code gets right, a lot of declarations and additional \CPP\ code have to be added to the file. This is done by declaring some additional strings that get appended to the front, middle and back of the bison file when it is produced. These additional lines essentially contain the rest of the \CPP\ implementation of the interface specified above. There are three static variables holding text: \begin{itemize} \item [[initial_lines]] will hold text that is put to the very beginning of the resulting bison file. \item [[before_lines]] will hold text that is put just before the \verb+%%+ line that starts the rules part of the bison file. \item [[after_lines]] will be put behind a second \verb+%%+ line and will contain additional \CPP\ code. \end{itemize} The corresponding integer variables will be used to turn these string arrays into [[Attribute]]s, which in turn are held in the corresponding attribute variables. <>= %{ static char *initial_lines[] = { "/************************************************** \n", " * This is a prettyprinting parser implementation * \n", " * file generated by pretzel. (It's Bison code!) * \n", " * * \n", " *************************************************/ \n\n", <> "/************************************************* \n", " * various user definitions start here: * \n", " *************************************************/ \n\n" }; static char *before_lines[] = { "/************************************************* \n", " * some pretzel definitions start here: * \n", " ************************************************/ \n\n", <> "\n" }; static char *after_lines[] = { "/************************************************* \n", " * additional pretzel code starts here: * \n", " *************************************************/ \n\n", <> "/************************************************* \n", " * optional user defined C code follows here: * \n", " *************************************************/ \n\n" }; static const int initial = sizeof(initial_lines)/sizeof(initial_lines[0]); static const int before = sizeof(before_lines)/sizeof(before_lines[0]); static const int after = sizeof(after_lines)/sizeof(after_lines[0]); static Attribute *initial_text = create(null); static Attribute *before_text = create(null); static Attribute *after_text = create(null); %} @ All these lines are accumulated into the three static variables and are inserted into the file within the grammar specified in section \ref{sec:grammarrules} on page \pageref{sec:grammarrules}. Using the constants like [[after]] spares us from counting the line numbers every time we change the text. Thanks to Andreas Kirschbaum for suggesting this hack. <>= int i=0; for (i=0; i>= "%{ \n\n", " /* this is needed for the yyprint function below */ \n", "#include \n\n", " /* include the attribute definitions */ \n", "#include\"attr.h\" \n\n", " /* include the output definitions */ \n", "#include\"output.h\" \n\n", " /* enable parser debugging */ \n", "#define YYDEBUG 1 \n\n", " /* redefine the semantic value */ \n", "#define YYSTYPE Attribute* \n\n", " /* enable calls of YYPRINT */ \n", "#define YYPRINT(file, type, value) yyprint (file, type, value)\n\n", " /* this is the prototype for yyprint */ \n", "static void \n", "yyprint(FILE *file, int type, YYSTYPE value); \n\n", " /* make sure that our local copy of yylex is \n", " * declared with name `yylex' and as a static \n", " * function. This should trick the parser into \n", " * calling the scanner object stored in \n", " * `static_scanner' (see below). */ \n\n", " /* undefine yylex to make sure it isn't renamed \n", " * by any command line option (e.g. -P). */ \n", "#undef yylex \n", " /* declare our local `dummy' yylex */ \n", "static int yylex(YYSTYPE *rvalue); \n", " /* make sure any newer versions of Bison don't \n", " * redeclare it differently */ \n", "#define YYLEX_DECL \n", "%} \n\n", @ Within the [[before_lines]] we have to put everything that can be redefined by the user and has to be mentioned before the body of [[yyparse]] comes along. <>= "%{ \n\n", "#include \n", " /* include own header only in default case: */ \n", "#ifndef PPARSE_NAME \n", "#include \"Ppparse.h\" \n", "#endif \n\n", " /* this is a definition of the yyerror routine */ \n", "int yyerror (const char *s) \n", "{ /* ignore error messages by BISON */ \n", " /* trick! use s do get around warning `s not used'. */\n", " if (1==0) fprintf(stderr, \"%s\", s); \n", " return 0; \n", "} \n\n", " /* enable parser debugging */ \n", "#define YYDEBUG 1 \n\n", " /* variable to hold the parsed attribute */ \n", "static Attribute *rest=create(null); \n\n", " /* include the scanner only in the default case: */ \n", "#ifndef PSCAN_NAME \n", "#define PSCAN_NAME Ppscan \n", "#include \"Ppscan.h\" \n", "#endif \n\n", " /* trick the yyparse function to use the scan member \n", " * of the scanner class: */ \n", "static Pscan* static_scanner = NULL; \n", "static int yylex( YYSTYPE *rvalue ) \n", "{ \n", " return(static_scanner->scan(rvalue)); \n", "} \n\n", "%} \n\n", "%pure_parser \n\n", @ The [[after_lines]] contain the rest of the definition of the implemented class. The actual prettyprinter previously did as many calls to [[yyparse]] as were necessary to reach [[eof]]. Now, [[yyparse]] is called exactly once. This makes a description of the prettyprinter semantics to the outside world easier (``input must be fully parseable''). However, we still empty the input stream up to [[eof]] to keep the semantics of the old prettyprinter d'accord with the new one. <>= "#ifndef PPARSE_NAME \n", "#define PPARSE_NAME Ppparse \n", "#endif \n\n", "PPARSE_NAME::PPARSE_NAME() \n", "{ \n", "} \n", "PPARSE_NAME::~PPARSE_NAME() \n", "{ \n", " static_scanner = NULL; \n", "} \n", "int PPARSE_NAME::prettyprint(istream* is, ostream* os) \n", "{ \n", " Latex_cweb_output ppoutput(*os); \n", " return(prettyprint(is, &ppoutput)); \n", "} \n", "int PPARSE_NAME::prettyprint(istream* is, Output* outp)\n", "{ \n", " int ret_val = 0; \n", " PSCAN_NAME ppscanner(is); \n", " static_scanner = &ppscanner; \n", " ret_val=yyparse(); \n", " while (!(is->eof())) { \n", " char c; \n", " is->get(c); \n", " } \n", " rest->print(*outp); \n", " return(ret_val); \n", "} \n\n", "void PPARSE_NAME::debug_on() { yydebug = 1; } \n", "void PPARSE_NAME::debug_off() { yydebug = 0; } \n\n", " /* This is a routine to print the semantic value */\n", "static void \n", "yyprint(FILE *file, int type, YYSTYPE value) {\n", " Latex_cweb_output os(cerr);\n", " value->print(os);\n", "}\n", @ \end{impls} \subsection{Error Diagnosis and Debugging} The error diagnosis functions can be used, if the [[build]] function has returned an error code (1). Calling [[error_text]] will result in a more elaborate explanation of the error cause (mostly ``syntax error'') and [[error_line]] will reveal the line number of the formatted token file, where the generator choked. \begin{impls} The implementation is straighforward again. The [[error_text]] function simply returns the internal error message and the [[error_line]] function askes the scanner and returns its line value. <>= char *Pparse_builder::error_text() { return(error_message); } int Pparse_builder::error_line() { return(scanner->line()); } @ The debugging member functions \ldots % XXX \end{impls} \begin{impls} \section{Bison Implementation of the Generator} \label{sec:grammarrules} This section contains the complete bison rules for the generator function [[yyparse]]. It is the main part of the implementation. All this was written for GNU bison version 1.19. \subsection{Token Declarations} Bison will expect the scanner to return the following tokens: <>= %token ID %token DOLLARS %token STRING %token FMTCMD %token A_LINE %token PERCENT_PERCENT %token UNKNOWN %token BEG_CODE %token CODE %token END_CODE @ \subsection{The Grammar Rules} Now we'll go through the grammar rules one by one in a top down fashion. A formatted grammar file consists of lots of top lines, a final top line (containing `\verb+%%+') and a list of productions that may be followed by again a `\verb+%%+' and another block of lines. If we want to insert stuff into the definitions section of the output, we have to do this between [[$1]] and [[$2]] of the join command below. <>= prebison_file : lines PERCENT_PERCENT prod_list { rest=$$=join(initial_text,$1, before_text,$2,$3, create("\n%%\n"),after_text);} | lines PERCENT_PERCENT prod_list PERCENT_PERCENT lines { rest=$$=join(initial_text,$1, before_text,$2,$3,$4,$5,after_text);} ; lines : /* empty */ {rest=$$=create(null);} | lines A_LINE {rest=$$=join($1,$2);} ; @ Here is the definition of the production list. It may be empty! <>= prod_list : /* empty */ {rest=$$=create(null);} | prod_list prod {rest=$$=join($1,$2,create("\n"));} ; @ Now we will see, what a production can be: A production starts with an [[ID]] followed by an `[[:]]'. The tail of a production can vary, but it has to be ended with a `[[;]]'. <>= prod : ID ':' prod_tail ';' {rest=$$=join( create("\n"), $1, create("\t\t: "), $3, create("\n;") );} ; @ The tail of a production can contain a long (or possibly empty) list of right sides. <>= prod_tail : right_side_list ; @ The definition of the [[right_side_list]] ensures, that several right sides of rules may be concatenated with `\verb+|+'. <>= right_side_list : right_side {rest=$$=$1;} | right_side_list '|' right_side {rest=$$= join( $1, create("\n\t\t| "), $3 );} ; @ If the right side of the rule is empty, a null-attribute will be the attribute of the right side. This is sometimes a little misleading, because this [[null]] command is not visible (neither physically nor in the documentation). Semantic values should be really empty. But I know of no easy way to resolve this problem. In fact, I can't figure out how to do it without returning a special marker and having the parser check every semantic value before [[join]]ing. <>= right_side : /* empty */ {rest=$$=create( "/* empty */\t\t {rest=$$=create(null);}" );} ; @ If the right side contains nothing but an [[id_list]], the default mechanism darts into action. The corresponding attribute consists simply of a list of all the attributes of the right side of the rule. Note that a list is not needed if only one identifier sleeps on the right side. Then we can say: % \begin{quote} [[rest=$$=$1;]] \end{quote} % But the join function works also with only one parameter so we can say % \begin{quote} [[rest=$$=join($1);]] \end{quote} % and make the code a little simpler. Note also that [[list_length]]$\geq 1$ if an [[id_list]] has been parsed. I have built in a mechanism, so that [[join]] is only invoked with a maximum of two arguments. This mechanism works as follows: \begin{itemize} \item Every time a new [[$i]] is added, the string % \begin{quote} [["join($i,"]] \end{quote} % is added to the [[ostringstream istr]]. Simultaneously a ``[[)]]'' is added to a second [[ostringstream jstr]]. So every ``[[(]]'' has a matching ``[[)]]'' in [[jstr]]. This is done as long as there is still at least one [[$i]] to add. \item The last [[$i]] is added simply as \begin{quote} [["$i"]] \end{quote} \item The resulting attribute is created by simply concatenating \begin{quote} [["\t\t{rest=$$="]] \end{quote} with [[istr.str()]] and [[jstr.str()]] and \begin{quote} [[";}"]] \end{quote} \end{itemize} <>= right_side : id_list { std::ostringstream istr; std::ostringstream jstr; for (int i=1; i>= %{ #include static int list_length=0; %} @ Of course you are also allowed to have an empty [[id_list]]. <>= right_side : attr_def {rest=$$=join( create("/* empty */"), create("\t\t\t"), $1 );} ; @ The normal case sees an [[id_list]] with an attribute definition at the end. From version 2.0 of \pretzel{} onwards we'll also allow code fragments to be inserted at the beginning of, within or at the end of the attribute definition. Initial and ending code is optional, but an attribute definition is necessary if you want to specify either or. The initial code will be placed in front of the [[$$]] assignment, ending code behind it. Code fragments in the middle are expected to return [[Attribute*]] and are simply [[join]]ed together like everything else. <>= right_side : id_list opt_code '{' attr_def '}' opt_code {rest=$$=join( $1, create("\t\t{ "), $2, create("\n\t\t\t"), create("rest=$$=\n"), $4, create(";\n\t\t"), $6, create("\n\t\t}"));} ; @ Let's say, what [[code]] and [[opt_code]] are first. <>= code : BEG_CODE code_lines END_CODE { rest=$$=$2; } ; code_lines : CODE { rest=$$=$1; } | code_lines CODE { rest=$$=join($1, create("\t\t\t"), $2); } ; opt_code : code { rest=$$=$1; } | /* empty */ { rest=$$=create(null); } ; @ [[list_length]] counts the number of identifiers on the right side of the rule to allow a correct number of [[$i]]'s in the default rule, that is if the attribute definition is missing. <>= id_list : ID {rest=$$=$1; list_length=1;} | id_list ID {rest=$$=join($1,create(" "),$2); list_length++; } ; attr_def : attr_def_list { rest=$$=join( create("\t\t\t"), $1 );} ; @ Note that the [[attr_def_list]] must contain at least one element Also, in version 2.0 of pretzel we'll allow to omit the [[+]]. <>= attr_def_list : attr {rest=$$=$1;} | attr_def_list '+' attr { rest=$$=join( create("join(\n\t\t\t\t"), $1, create(",\n\t\t\t\t"), $3, create(")") );} | attr_def_list attr { rest=$$=join( create("join(\n\t\t\t\t"), $1, create(",\n\t\t\t\t"), $2, create(")") );} ; attr : DOLLARS {rest=$$=$1;} ; @ The scanner returns the name of the format-command as semantic value. This command shall be created in the output file. Therefore we must say: % \begin{quote} create this: [["create(" + name of the format command + ")"]] \end{quote} % This yields: % \begin{quote} [[join(create("create("),$1,create(")"))]] \end{quote} <>= attr : FMTCMD {rest=$$=join( create("create("), $1, create(")") );} ; @ A similar thought goes with strings. The scanner returns the contents of the string packed up nicely into double quotes. The only thing the parser has to to is: % \begin{quote} create this: [["create(" + string in double quotes + ")"]] \end{quote} % This can be said as follows: % \begin{quote} [[join(create("create("),$1,create(")"))]] \end{quote} <>= attr : STRING {rest=$$=join( create("create("), $1, create(")") );} ; @ An attribute can be code too, at least from version 2.0 of \pretzel{} onwards. <>= attr : code { rest=$$=$1; } ; @ \section{Additional bison Functions} Here's the definition of the [[yyerror]] routine needed by the generated parser. It isn't supplied automatically, so we have to cater for it. We don't want to output any bison error messages so we simply return 0. Its name has to contain the same prefix as specified on the bison command line. <>= int Pretzel_fgerror (const char *s) { return 0; } @ This line is needed so that Bison doesn't declare the supposed [[yyerror]] routine extern. <>= %{ int Pretzel_fgerror (const char *s); #define YYERROR_DECL %} @ \end{impls} \begin{bigspecs} \section{Examples} This section contains some examples of how to use the [[Pparse]] class and subclasses. [\ldots] \end{bigspecs} \end{document} % % $Log: fgparse.nw,v $ % Revision 1.8 1998/06/11 10:59:14 felix % changed reference is.get to is->get of course. Typical example of % bug introduced by changes. % % Revision 1.7 1998/04/25 09:03:18 gaertner % Added a note on empty rules to documentation. % Changed generated prettyprinter code to do exactly one parse. % This makes sematics in error cases easier. % % Revision 1.6 1996/09/17 13:45:40 gaertner % Changed the decaration and definition of yylex in the generated % parser so that it works with g++ and diferent versions of Bison. % % Revision 1.5 1996/09/12 18:44:10 gaertner % Refined declarartion handling of yylex and yyerror. % % Revision 1.4 1996/09/12 18:00:55 gaertner % Changed the yylex function to static. Hope the trick of having % yyparse call the local yylex works now. I've taken care that % several macros are defined okay (e.g. yylex and YYLEX_DECL). % % Revision 1.3 1996/04/22 09:18:37 gaertner % Allows user code in attribute definitions now. % % Revision 1.2 1996/03/21 11:04:23 gaertner % Added epty implementations to Pparse constructor and destructor. % Refined generated output so it will compile. % % Revision 1.1 1996/03/21 08:13:57 gaertner % Initial revision % % pretzel-2.0n-2/fgrammar/index.list0000644000000000000000000000061406360670556015671 0ustar rootrootthis directory & the prettyprinting parser generator Makefile & the Makefile README & more information fgparse.nw & specs and implementation of the generator class fgrammar.nw & tester for the module fgscan.nw & specs and implementation of a scanner for formatted grammar files. pascal.fg & test input for regression test test.output.correct & correct test output of fgrammar for regression test pretzel-2.0n-2/fgrammar/fgscan.nw0000644000000000000000000004554310765025075015500 0ustar rootroot% This is a file written using noweb % % $Id: fgscan.nw,v 1.4 1996/09/12 18:43:53 gaertner Exp $ % \documentclass{article} \usepackage{a4,version,pretzeldoc,noweb} \begin{document} \includeversion{bigspecs} %\includeversion{impls} %\excludeversion{bigspecs}% without elaborate specification \excludeversion{impls}% without implementation \title{A Scanner for Formatted Grammar Files} \author{Felix G\"artner} \maketitle \begin{abstract} This document describes the interface \begin{impls}and implementation\end{impls} of a scanner for formatted grammar files. A formatted grammar file is a file containing a description of a grammar for prettyprinting a certain programming language which is enhanced with format commands. It is used within the framework of the ``pretzel'' project. Pretzel is a universal prettyprinter generator. \end{abstract} \tableofcontents \section{Introduction} A {\em prettyprinting parser} is a parser that does prettyprinting as a result of parsing. Such a parser normally uses an attribute grammar, i.e.~every token has an associated attribute. These attributes specify how the token looks. An attribute grammar that contains such prettyprinting information will be called a {\em formatted grammar}. Together with information about the formatting of terminal tokens (so called {\em formatted tokens}) a formatted grammar defines a prettyprinter. The ``pretzel'' project aims to generate such a prettyprinter automatically from formatted token and formatted grammar description laid down in files of a special format. These files are called the {\em formatted tokens file} and the {\em formatted grammar file}. The precise format of these files can be obtained by reading the main documentation of the pretzel project. I will assume that you know about this and also about the prettyprinting method that the generated prettyprinter uses. This document describes the interface \begin{impls}and implementation\end{impls} of a program that is used to generate such a prettyprinting parser. It is a scanner to scan formatted grammar files. This scanner is used by the actual generator routine that creates the prettyprinting parser. This is an overview over the frame of the header file for the scanner: <
>= #ifndef FGSCAN_H #define FGSCAN_H <
> <> #endif @ \begin{impls} The implementation will use the flex scanner generator (installed on the development site is version 2.4.6). We won't use the feature of flex to create a \CPP\ scanner class, because we want to stick with stuff that has been tested and that will probably work. A flex file has the following frame. <>= %{ #include"fgscan.h" /* include own header */ %} <> %% <> %% <> @ \end{impls} \section{Interface (Overview)} This section describes the interface of the scanner that scans formatted grammar files. Formatted grammar files contain a context free grammar which is enhanced by formatting instructions. A formatted grammar file is used to build a prettyprinter for the so specified programming language. There are three things we want to do with the scanner: \begin{itemize} \item Create a new scanner and initialize it to tell it where to take the input characters from. \item Call it, to know, which token is next in the input stream (this is called ({\em scanning}). \item Destroy the scanner explicitly (to free memory, clean up or get ready for a new formatted grammar file). \end{itemize} Here's the declaration of the new scanner class. <>= class Fgscanner { public: Fgscanner(istream*); /* create and initialize new scanner */ ~Fgscanner(); /* remove a scanner */ int scan(Attribute**); /* scan for a new token */ int line(); /* returns line number of last token scanned */ <> }; @ The function [[line]] is an additional member function aimed to help debugging. The [[scan]] member function returns the token code of the next token together with a textual description of the details as a reference argument of type [[Attribute*]]. See the {\tt attr.nw} file for a description of this class. Anyway, we have to include these headers. <
>= #include"attr.h" /* the Attribute class */ #include using namespace std; @ \section{Interface (Details)} In this section I will present every member function of the new scanner class in a detailed fashing for a complete reference\begin{impls} and will explain the ideas and details behind the implementation\end{impls}. \begin{impls} A scanner generated by flex is mainly a function called [[yylex]] that scans from a given [[FILE*]] and returns token codes as integers. We'll use this function to scan the formatted token file and to return an additional string with the token code that describe the token in more detail and can be used to piece together the target file implementing the prettyprinting scanner. We'll use the [[Attribute]] class for this purpose. (Though it wasn't designed for it, we can still use it here.) We also have to redefine the interface for [[yylex]] to suit these requirements. <>= %{ #undef YY_DECL #define YY_DECL int yylex(Attribute* *rvalue) %} @ By default, the name of the scanner function is [[yylex]]. By specifying the {\tt -P} option at the command line you can redefine the ``yy'' prefix and thus change the name of the scanner function. The implementation expects that the scanner is generated using the option ``{tt -PPretzel_fg}'' and thus will expect the scanner function to be called: % \begin{quote} [[Pretzel_fglex]] \end{quote} \end{impls} A short word about using multiple scanners within one program: Because of drawbacks of the underlying algorithm \begin{impls}(the interface of flex)\end{impls} the resulting scanner is not reentrant and using multiple instances of the scanner class in the same program will be extremely hazardrous. This might seem a severe drawback, but isn't too bad in the end, because it was built to be used in only one instance. \begin{impls}This is also the reason why I shouldn't have used a class to implement it, but the interface was designed before learning about flex' deficiencies.\end{impls} \begin{impls} Because of the above note, we'll use static variables instead of private members to handle the private information of the class. <>= /* none */ @ We want the scanner to read from an input stream and not from a [[FILE*]], so we have to take care about this. We'll define a static variable that holds the [[istream]] object pointer and will be used by the scanner. <>= %{ static istream* yyin_stream; %} @ Also, we have to modify the way, in which [[yylex]] reads it's data. This is done by redefining the [[YY_INPUT]] macro. Thanks to Christine Detig for the hint. <>= %{ #undef YY_INPUT #define YY_INPUT(buf, result, max_size) { \ if (yyin_stream->eof()) result=YY_NULL; \ else { \ yyin_stream->read(buf, max_size); \ result=yyin_stream->gcount(); \ } \ } %} @ The current line number has to be stored somewhere too. This is done within the static variable [[line]]. <>= %{ static int line_number = 1; %} @ \end{impls} \subsection{Creating the new Scanner} The constructor of the [[Fgscanner]] class creates a new scanner for formatted grammar files. You have to specify an [[istream]] pointer, which is the stream from which the tokens are read. \begin{impls} The implementation of the constructor is pretty easy. It simply stores the given input stream pointer and resets the line number count. The line number is initially set to 1 since we have no line 0. <>= Fgscanner::Fgscanner(istream* is) { line_number = 1; yyin_stream = is; } @ \end{impls} \subsection{Destroying a Scanner} The [[~Fgscanner]] simply destroys the specified scanner again. An [[Fgscanner]] is a one time use object. To start reading from a new input stream you should first destroy the old scanner and then create a new one using the constructor. \begin{impls} This is implemented by resetting the internal scanner in case we want to scan a new formatted token file. Note that although the scanner object dissappears, the internal scanner state still is valid. <>= Fgscanner::~Fgscanner() { yyrestart(NULL); } @ \end{impls} \subsection{Scanning} The next function is the normal scanner member function called [[scan]]. It returns token codes as integer values together with the corresponding attribute (as a call by reference argument). Table \ref{tab:returnvalues} shows all the possible values that [[scan]] might return. They are partly defined as \C\ macros, and partly simply the character values of the given symbols. The macros are defined in a header file that is generated by the parser for formatted token files (the file {\tt fgramdefs.h}). See the specifications in {\tt fgparse.nw} for details. From version 2.0 onwards \pretzel{} allows inclusion of code within attribute definitions. There are three additional tokens that the scanner detects: [[BEG_CODE]], [[CODE]], and [[END_CODE]]. They refer to the starting code delimiter within attribute definitions (usually a ``{\tt ]}''), a code line within, and the corresponding closing delimiter. \begin{impls} The implementation has to include this header file. <>= %{ #include "fgramdefs.h" %} @ \end{impls} \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{IlIp{5cm}I} \hline token & comment \\ \hline \verb+PERCENT_PERCENT+ & A line containing only `\verb+%%+'. \\ \verb+A_LINE+ & A line from the definitions part or the \C\ code part. \\ \verb+DOLLARS+ & Any symbol from `\verb+$1+' to `\verb+$9+'. \\ \verb+STRING+ & A string from an attribute definition. \\ \verb+{+ & Start of attribute definition. \\ \verb+}+ & End of attribute definition. \\ \verb#+# & Concatenation inside attribute definition. \\ \verb+;+ & Semicolon. \\ \verb+:+ & Colon. \\ \verb+I+ & Vertical line. \\ [[BEG_CODE]] & starting code delimiter in attribute definitions \\ [[CODE]] & a line of code in attribute definitions \\ [[END_CODE]] & ending code delimiter in attribute definitions \\ \verb+FMTCMD+ & A format command. \\ \verb+ID+ & A token identifier. \\ \verb+UNKNOWN+ & A set of unmatched characters. \\ \hline \end{tabular} \caption{(Symbolic) return values of the [[scan]] member function.} \label{tab:returnvalues} \end{center} \end{table} Basicly a formatted grammar file contains a prelude of definitions and \C\ code which is followed by a line containing ``\verb+%%+''. Then follow a set of grammar rules which are enhanced by formatting instructions. Optionally there may be an additional line with ``\verb+%%+'' followed by \C\ code. The [[scan]] member function returns the semantic value (i.e.~part of the text to build the prettyprinting parser) as a call by reference argument. \begin{impls} The [[scan]] member function is a delayed call to [[yylex]]. <>= int Fgscanner::scan(Attribute* *rvalue) { return(yylex(rvalue)); } @ The exact behaviour, i.e.~a complete specification of the flex regular expressions can be found in section \ref{sec:flexbody} on page \pageref{sec:flexbody}. \end{impls} \subsection{Debugging} There is an additional member function that can be used for debugging purposes. The value of [[line()]] returns the line number that the token was in that was last returned. \begin{impls} Looking at the implementation we have to note that the internal variable has to be incremented every time we scan a newline in the input file. This has to be checked in the definitions of section \ref{sec:flexbody} and is a possible bug source! <>= int Fgscanner::line() { return(line_number); } @ \end{impls} \begin{impls} \section{The flex Token descriptions} \label{sec:flexbody} This section contains the complete flex implementation of the scanner class. Note that we have to increment the current line number every time we encounter and scan a newline. The really important things in the formatted grammar file are the lines inbetween the \verb+%%+ tokens (or between the first and the end of the file if no user code is given). So we'll have the scanner ignore everything from the beginning of the file up to the first two percents and then start it's real work. We'll distinguish between these two states using an exclusive start condition [[R]] (for ``rules''). <>= %x R @ Now lets have a look on how the scanner reads the top lines and gets into this start condition. When the scanner finds the first `\verb+%%+', he'll return a [[PERCENT_PERCENT]] token and switch into ``rules'' mode. Until he finds such a line, he'll keep on returning the prelude of the file line by line. <>= ^"%%"\n {*rvalue=create(yytext); BEGIN(R); line_number++; return PERCENT_PERCENT;} .*\n *rvalue=create(yytext); line_number++; return A_LINE; @ So let's assume we are in ``rules mode''. Then we basicly know what we can expect. These are the `reserved words': <>= /* references to semantic values of tokens */ "$"[1-9] *rvalue=create(yytext); return DOLLARS; /* strings */ \"[^\"]*\" *rvalue=create(yytext); return STRING; /* special delimiters */ "{" | "}" | "+" | ";" | ":" | "|" *rvalue=create(yytext); return yytext[0]; @ Before we continue with looking at the format commands, here's the stuff needed for version 2.0 of \pretzel{}. We need to detect code parts within attribute definitions. The opeing and closing delimiters for code will be angled brackets. If we encounter such an opening delimiter, we have to return all code up to the closing delimiter line by line. Because this is again a different context of speach, we need an additional (exclusive) start condition. It will be called [[AC]] for ``attribute code''. <>= %x AC @ <>= "[" *rvalue=create(yytext); BEGIN(AC); return BEG_CODE; @ Before we continue, a short thought: Say, we've seen an opening code delimiter and we're in [[AC]] mode. Now all lines must be returned up to the point where we find a matching closing delimiter. Closing delimiters (usually an angled bracket) must be escaped if they are used within the code. The escape character is stripped off when the string is returned using the [[unescaped]] function. <>= (([^\]\n])|(\\\]))* { *rvalue=create(unescaped(yytext)); return CODE; } (([^\]\n])|(\\\]))*\n { *rvalue=create(unescaped(yytext)); line_number++; return CODE; } "]" *rvalue=NULL; BEGIN(R); return END_CODE; @ The [[unescaped]] function removes backslashes from a given string if they are followed by a closing delimiter (currently a `{\tt ]}'). The string length shrinks by the number of backslashes removed. [The same routine appears in the file {\tt ftscan.nw}. That's why it's declared [[static]]. It should be part of the pretzel library.] The implementation has two pointers into the array. The first points to the position where the next unescaped character should be placed, the second one holds the position of the next character to be inspected. We only shorten the given string. That's why we don't [[malloc]] storage and work on a copy. <>= %{ static char* unescaped(char* s) { int left = 0; /* next position to place [[s[right]]] */ int right = 0; while (s[right] != 0) { // should be `!= NULL', but some // compilers choke on it if ((s[right] == '\\') && (s[right+1] == ']')) { right++; } s[left] = s[right]; left++; right++; } s[left] = s[right]; /* terminate string */ return(s); } %} @ So let's continue now with the format commands we can find. <>= /* format commands */ null | indent | outdent | opt0 | opt1 | opt2 | opt3 | opt4 | opt5 | opt6 | opt7 | opt8 | opt9 | backup | break_space | force | big_force | no_indent | cancel *rvalue=create(yytext); return FMTCMD; /* abbreviations: */ bsp *rvalue=create("break_space"); return FMTCMD; b_force *rvalue=create("big_force"); return FMTCMD; @ Here is the rule for normal token identifiers. Note that only uppercase is allowed! <>= [A-Za-z][A-Za-z0-9_]* *rvalue=create(yytext); return ID; @ We eat up whitespace within the rules part and neglext comments. <>= [\ \t] /* eat up whitespace */ \n line_number++; /* but count lines */ "//".* /* and neglect comments */ @ To finish off the rules, we have to lookout for another two percent signs in a line by themself <>= ^"%%"\n { *rvalue=create(yytext); BEGIN(INITIAL); line_number++; return PERCENT_PERCENT; } @ For any other character that doesn't match one of the other rules, we return an [[UNKNOWN]] token. <>= . return(UNKNOWN); . return(UNKNOWN); @ \section{Additional flex functions} This section contains the definition of the [[yywrap]] function needed to complete a flex scanner. Returning 1 means that the scanner can exit when receiving an end of file indication. The [[extern "C"]] is due to Lee Wittenberg (Thanks!) to get around linking problems with some versions of gcc. <>= %{ extern "C" int yywrap() { return(1); } %} @ \end{impls} \end{document} % % $Log: fgscan.nw,v $ % Revision 1.4 1996/09/12 18:43:53 gaertner % Added extern "C" (thanks Lee). % % Revision 1.4 1996/09/12 18:43:53 gaertner % Added extern "C" (thanks Lee). % % Revision 1.3 1996/09/02 16:03:28 gaertner % Fixed the `unescaped' routine to work with g++. % % Revision 1.2 1996/04/22 09:18:20 gaertner % Allows user code in attribute definitions now. % % Revision 1.1 1996/03/21 08:13:57 gaertner % Initial revision % % pretzel-2.0n-2/fgrammar/README0000644000000000000000000000113106123767107014534 0ustar rootrootSome hints to the files in this directory: Makefile fgparse.nw specs and implementation of the generator class fgscan.nw specs and implementation of a scanner for formatted grammar files. fgrammar.nw tester for the module pascal.fg test input for regression test test.output.correct correct test output of fgrammar for regression test To get the header for the abstract base class of every prettyprinting parser, type: make Pparse.h To get it for your generated parser class, type: make Ppparse.h (note the triple `p'). Look into the big specs of fgparse.nw for details. pretzel-2.0n-2/fgrammar/index.html0000644000000000000000000000237106360670566015665 0ustar rootroot Index file for directory "pretzel/fgrammar" of Pretzel distribution

Index file for directory "pretzel/fgrammar" of Pretzel distribution

Files and directories are:

this directory

    the prettyprinting parser generator
Makefile
    the Makefile
README
    more information
fgparse.nw
    specs and implementation of the generator class
fgrammar.nw
    tester for the module
fgscan.nw
    specs and implementation of a scanner for formatted grammar files.
pascal.fg
    test input for regression test
test.output.correct
    correct test output of fgrammar for regression test

Felix Gaertner

To Pretzel Homepage.

Last modified: Wed Jul 9 13:09:43 MESZ 1997 pretzel-2.0n-2/fgrammar/Makefile0000644000000000000000000001621206537744626015334 0ustar rootroot# $Id: Makefile,v 1.13 1996/09/12 18:43:27 gaertner Exp gaertner $ # ---------------------------------------------------------------------- # # Makefile for formatted grammar file scanner and parser # # ---------------------------------------------------------------------- # Here are the things that determine the configuration: # ---------------------------------------------------------------------- # what compiler do we use? CC = g++ # de-comment this if you want a debug version: #DBVERSION = -D XXX # compiler flags: CFLAGS = -g -I../include -L.. -lpretzel # prefix for globals of scanner and parser (`yy' by default) GLOBALSPREFIX = Pretzel_fg # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # You probably don't need to change anything from here: # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- # Groups of files: # all noweb sources NOWEBS = fgscan.nw fgparse.nw fgrammar.nw # root chunk name of headers HEADERCHUNK = header # root chunk name of C implementation IMPLEMENTATIONCHUNK = implementation # root chunk name of flex implementation FLEXIMPLCHUNK = flex-implementation # root chunk name of bison implementation BISONIMPLCHUNK = bison-implementation # all `WEB' sources (old) #WEBS = fgscan.spc fgscan.l fgparse.spc fgparse.y fgrammar.w # all other program WEB sources (old) #ETCWEBS = pparse.spc # all TeX documents TEXDOCS = # all other files for the distribution DISTFILES = Makefile pascal.fg test.output.correct README # name of the distribution package DISTNAME = # Which program to make by default: PROG = fgrammar # objects of this program: OBJS = fgscan.o fgparse.o fgrammar.o # objects to be released: RELOBJS = fgparse.o fgscan.o # C sources of this program: CSRCES = fgscan.c fgparse.c fgrammar.c # intermediate products from which C sources are made INTERMEDIATES = fgscan.l fgparse.y # crap to be removed when making clean: OTHERCRAP = fgparse.aux fgparse.dvi fgparse.idx fgparse.log \ fgparse.scn fgparse.tex fgparse.toc \ fgscan.aux fgscan.dvi fgscan.idx fgscan.log \ fgscan.scn fgscan.tex fgscan.toc \ fgscan.l fgparse.y \ pparse.dvi pparse.idx pparse.log pparse.scn \ pparse.tex pparse.toc \ Pparse.h Ppparse.h \ fgrammar.aux fgrammar.dvi fgrammar.idx fgrammar.log \ fgrammar.scn fgrammar.tex test.output # ---------------------------------------------------------------------- # these are all the headers for the compiler HEADERS = fgscan.h fgparse.h fgramdefs.h Pparse.h Ppparse.h # these are all the objects for the compiler OBJECTS = $(OBJS) # these are all the C sources to make the objects CSOURCES = $(CSRCES) # These are all of the flags for the compiler: CCFLAGS = $(CFLAGS) $(DBVERSION) # these are all C sources that might possibly crop up ALLCSRCS = $(CSOURCES) # these are all object files that may appear ALLOBJS = $(OBJECTS) # these are all header files produced from WEBs that may appear ALLHEADERS = $(HEADERS) # these are all the executables that could be produced ALLPROGS = $(PROG) # ---------------------------------------------------------------------- CWEAVE = cweave CTANGLE = ctangle NOTANGLE= notangle NOWEAVE = noweave TEX = tex DVIPS = dvips REMOVE = rm -f MAKE = make LEX = flex #LEX = lex YACC = bison #YACC = yacc TEX = tex LATEX = tex-it latex CPIF = cpif # ---------------------------------------------------------------------- BISONOPTIONS = -p$(GLOBALSPREFIX) FLEXOPTIONS = -L -P$(GLOBALSPREFIX) # ---------------------------------------------------------------------- .SUFFIXES: .nw .spc .ps .tex .dvi .w .c .o .h # overall rules: .nw.tex: $(NOWEAVE) -delay $*.nw > $*.tex .w.tex: $(CWEAVE) $* .tex.dvi: $(LATEX) $< .w.dvi: $(MAKE) $*.tex $(MAKE) $*.dvi .dvi.ps: $(DVIPS) $< -o $*.ps .nw.h: $(NOTANGLE) -L -R$(HEADERCHUNK) $*.nw | $(CPIF) $*.h .nw.c: $(NOTANGLE) -L -R$(IMPLEMENTATIONCHUNK) $*.nw | $(CPIF) $*.c .nw.l: $(NOTANGLE) -R$(FLEXIMPLCHUNK) $*.nw | $(CPIF) $*.l .nw.y: $(NOTANGLE) -R$(BISONIMPLCHUNK) $*.nw | $(CPIF) $*.y .w.c: $(CTANGLE) $* .spc.h: $(CTANGLE) $*.spc - $*.h #.w.o: # $(MAKE) $*.c # $(MAKE) $*.o .c.o: $(CC) -c $*.c $(CCFLAGS) .y.c: $(YACC) $(BISONOPTIONS) $*.y mv $*.tab.c $*.c .l.c: $(LEX) $(FLEXOPTIONS) $*.l mv lex.$(GLOBALSPREFIX).c $*.c # ---------------------------------------------------------------------- # regenerate whole system: system: $(PROG) $(PROG): $(OBJECTS) $(CC) -o $@ $(OBJECTS) $(CCFLAGS) $(OBJS): $(HEADERS) $(CSRCES) $(CSRCES): $(INTERMEDIATES) # make the common token header file fgramdefs.h: fgparse.y $(YACC) -d fgparse.y mv fgparse.tab.h fgramdefs.h Ppparse.h: fgparse.nw $(NOTANGLE) -R"header file for prettyprinting parser" fgparse.nw >Ppparse.h Pparse.h: fgparse.nw $(NOTANGLE) -R"header file for abstract base class of [[Pparse]]" fgparse.nw >Pparse.h # list all source code: print: # apply lint to all C sources: lint: # regression: regression: $(PROG) ./fgrammar test.output if diff test.output test.output.correct; \ then echo "Regression test is fine."; \ else echo "Regression test failed."; \ fi # remove all intermediate products but not executables or sources! clean: $(REMOVE) $(ALLOBJS) $(ALLCSRCS) $(ALLHEADERS) $(OTHERCRAP) # remove everything that doesn't belong to original source: clobber: clean $(REMOVE) $(ALLPROGS) # bundle source files together into an archive: #bundle: # tar cf $(DISTNAME).tar \ # $(WEBS) $(ETCWEBS) $(TEXDOCS) $(DISTFILES) # copy executables into PATH directories, et al. install: # release a new version: release: $(HEADERS) $(RELOBJS) cp $(HEADERS) ../include ar vrus ../libpretzel.a $(RELOBJS) # ====================================================================== # # $Log: Makefile,v $ # Revision 1.13 1996/09/12 18:43:27 gaertner # Changed to g++ and noweb # # Revision 1.12 1996/03/21 08:14:06 gaertner # Changed to make it work with the new noweb versions of the files. # # Revision 1.11 1995/08/15 17:21:54 gaertner # Moved CC options to the end of the command line for portability. # # Revision 1.10 1995/08/15 16:52:53 gaertner # Catered for multiple scanners: Added variables GLOBALSPREFIX # and BISONOPTIONS/FLEXOPTIONS that instruct Bison and flex # to prefix all globals with `yyfgrammar'. # # Revision 1.9 1995/04/26 17:56:11 gaertner # Now README is recognized and bundled too. # # Revision 1.8 1995/04/26 17:50:13 gaertner # Compiling/releasing uses lpretzel library now. # You can make a regression test now. # Making dvi's uses LaTeX now. # # Revision 1.7 1994/10/31 19:04:32 gaertner # Now make bundle creates fgrammar.tar # # Revision 1.6 1994/10/24 16:51:50 gaertner # Now fgrammar.o isn't released anymore. # # Revision 1.5 1994/10/24 16:29:32 gaertner # Changed pscan.spc to pparse.spc (was a mistake). # # Revision 1.4 1994/10/24 16:19:41 gaertner # Added pscan.h as header. It is released too. # # Revision 1.3 1994/10/19 18:40:47 gaertner # Added dependency of fgramdefs.h file. # # Revision 1.2 1994/10/18 18:53:51 gaertner # First revision using the Makefile template. # # pretzel-2.0n-2/fgrammar/test.output.correct0000644000000000000000000002222706537733324017571 0ustar rootroot/************************************************** * This is a prettyprinting parser implementation * * file generated by pretzel. (It's Bison code!) * * * *************************************************/ %{ /* this is needed for the yyprint function below */ #include /* include the attribute definitions */ #include"attr.h" /* include the output definitions */ #include"output.h" /* enable parser debugging */ #define YYDEBUG 1 /* redefine the semantic value */ #define YYSTYPE Attribute* /* enable calls of YYPRINT */ #define YYPRINT(file, type, value) yyprint (file, type, value) /* this is the prototype for yyprint */ static void yyprint(FILE *file, int type, YYSTYPE value); /* make sure that our local copy of yylex is * declared with name `yylex' and as a static * function. This should trick the parser into * calling the scanner object stored in * `static_scanner' (see below). */ /* undefine yylex to make sure it isn't renamed * by any command line option (e.g. -P). */ #undef yylex /* declare our local `dummy' yylex */ static int yylex(YYSTYPE *rvalue); /* make sure any newer versions of Bison don't * redeclare it differently */ #define YYLEX_DECL %} /************************************************* * various user definitions start here: * *************************************************/ /* pretzel formatted grammar for simple PASCAL. */ %{ #define PSCAN_NAME pascan #define PSCAN_INIT_NAME pascan_init %} %token SEMI %token BEG %token END %token MATH // token should only be used in math mode %token SIMP // other simple tokens %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %token COMMENT %token ID_TYPE %token RECORD %token CASE /************************************************* * some pretzel definitions start here: * ************************************************/ %{ /* include own header only in default case: */ #ifndef PPARSE_NAME #include "Ppparse.h" #endif /* this is a definition of the yyerror routine */ yyerror (const char *s) { /* ignore error messages by BISON */ /* trick! use s do get around warning `s not used'. */ if (1==0) fprintf(stderr, "%s", s); return 0; } /* enable parser debugging */ #define YYDEBUG 1 /* variable to hold the parsed attribute */ static Attribute *rest=create(null); /* include the scanner only in the default case: */ #ifndef PSCAN_NAME #define PSCAN_NAME Ppscan #include "Ppscan.h" #endif /* trick the yyparse function to use the scan member * of the scanner class: */ static Pscan* static_scanner = NULL; static int yylex( YYSTYPE *rvalue ) { return(static_scanner->scan(rvalue)); } %} %pure_parser %% stmt_list : stmt {rest=$$=$1;} | stmt_list stmt {rest=$$=join($1,$2);} ; stmt : COMMENT { int i; rest=$$= join( join( create(cancel), (lookup() ? $1 : create(id))), create(null)); delete i; } | proc {rest=$$=$1;} | SEMI { rest=$$= join( join( create(cancel), $1), create(force)); } | BEG stmt_list END { rest=$$= join( join( join( join( join( join( join( $1, create(indent)), create(force)), $2), create(cancel)), create(outdent)), create(force)), $3); } | math {rest=$$=$1;} ; math : MATH {rest=$$=$1;} | math math {rest=$$=join($1,$2);} | simp {rest=$$=$1;} | COLON {rest=$$=$1;} | OPEN decl_list CLOSE {rest=$$=join($1,join($2,$3));} | RECORD stmt_list END {rest=$$=join($1,join($2,$3));} ; simp : SIMP {rest=$$=$1;} | identifier { rest=$$= join( join( create("\\\\{"), $1), create("}")); } ; identifier : ID_TYPE {rest=$$=$1;} | identifier ID_TYPE {rest=$$=join($1,$2);} ; decl_list : math {rest=$$=$1;} | INTRO math {rest=$$=join($1,$2);} | decl_list SEMI math { rest=$$= join( join( join( $1, $2), create(" ")), $3); } | decl_list SEMI INTRO math {rest=$$=join($1,join($2,join($3,$4)));} ; stmt : ALPHA math OMEGA stmt { rest=$$= join( join( join( join( join( join( join( join( $1, create(" ")), $2), create(" ")), $3), create(indent)), create(force)), $4), create(outdent)); } | ALPHA math OMEGA stmt ELSE stmt { rest=$$= join( join( join( join( join( join( join( join( join( join( join( join( join( join( $1, create(" ")), $2), create(" ")), $3), create(indent)), create(force)), $4), create(outdent)), create(force)), $5), create(indent)), create(force)), $6), create(outdent)); } | CASE math OMEGA stmt_list END {rest=$$=join($1,join($2,join($3,join($4,$5))));} | BEG stmt_list UNTIL math { rest=$$= join( join( join( join( join( join( join( join( join( $1, create(indent)), create(force)), $2), create(cancel)), create(outdent)), create(force)), $3), create(" ")), $4); } ; proc : proc INTRO math SEMI { rest=$$= join( join( join( join( $1, $2), $3), $4), create(force)); } | PROC {rest=$$=$1;} ; stmt : INTRO math SEMI { rest=$$= join( join( join( $1, $2), $3), create(force)); } ; %% /************************************************* * additional pretzel code starts here: * *************************************************/ #ifndef PPARSE_NAME #define PPARSE_NAME Ppparse #endif PPARSE_NAME::PPARSE_NAME() { } PPARSE_NAME::~PPARSE_NAME() { static_scanner = NULL; } int PPARSE_NAME::prettyprint(istream* is, ostream* os) { Latex_cweb_output ppoutput(*os); return(prettyprint(is, &ppoutput)); } int PPARSE_NAME::prettyprint(istream* is, Output* outp) { int ret_val = 0; PSCAN_NAME ppscanner(is); static_scanner = &ppscanner; ret_val=yyparse(); while (!(is->eof())) { char c; is->get(c); } rest->print(*outp); return(ret_val); } void PPARSE_NAME::debug_on() { yydebug = 1; } void PPARSE_NAME::debug_off() { yydebug = 0; } /* This is a routine to print the semantic value */ static void yyprint(FILE *file, int type, YYSTYPE value) { Latex_cweb_output os(cerr); value->print(os); } /************************************************* * optional user defined C code follows here: * *************************************************/ pretzel-2.0n-2/fgrammar/pascal.fg0000644000000000000000000000532106136647241015442 0ustar rootroot/* pretzel formatted grammar for simple PASCAL. */ %{ #define PSCAN_NAME pascan #define PSCAN_INIT_NAME pascan_init %} %token SEMI %token BEG %token END %token MATH // token should only be used in math mode %token SIMP // other simple tokens %token OPEN %token CLOSE %token ALPHA %token OMEGA %token UNTIL %token INTRO %token PROC %token COLON %token ELSE %token COMMENT %token ID_TYPE %token RECORD %token CASE %% stmt_list : stmt // collect everything on a | stmt_list stmt // list of `statements' ; // what can statements be? stmt : COMMENT [ int i;] {cancel [(lookup() ? $1 : create(id))] [create(null)]} [delete i;] | proc // procedure heading | SEMI // empty statement {cancel + $1 + force } | BEG stmt_list END // a block { $1 + indent + force + $2 + cancel + outdent + force + $3 } | math // an expression ; math : MATH // build something like an | math math // `expression' | simp | COLON | OPEN decl_list CLOSE | RECORD stmt_list END ; simp : SIMP | identifier { "\\\\{" + $1 + "}" } ; identifier : ID_TYPE // put together identifiers | identifier ID_TYPE ; decl_list : math // parameter lists | INTRO math // for var-parameters | decl_list SEMI math {$1 + $2 + " " + $3 } | decl_list SEMI INTRO math // for var-parameters ; stmt : ALPHA math OMEGA stmt // if then/while do etc. { $1 + " " + $2 + " " + $3 + indent + force + $4 + outdent } | ALPHA math OMEGA stmt ELSE stmt // if then else {$1 + " " + $2 + " " + $3 + indent + force + $4 + outdent + force + $5 + indent + force + $6 + outdent } | CASE math OMEGA stmt_list END // case of end | BEG stmt_list UNTIL math // repeat until { $1 + indent + force + $2 + cancel + outdent + force + $3 + " " + $4 } ; proc : proc INTRO math SEMI {$1 + $2 + $3 + $4 + force} | PROC // procedure heading ; stmt : INTRO math SEMI // variable and type declarations {$1 + $2 + $3 + force} ; pretzel-2.0n-2/files-to-exclude0000644000000000000000000001230406631470560015156 0ustar rootrootpretzel/ftokens/RCS pretzel/ftokens/RCS/ftscan.spc,v pretzel/ftokens/RCS/ftokens.nw,v pretzel/ftokens/RCS/ftparse.spc,v pretzel/ftokens/RCS/pscan.spc,v pretzel/ftokens/RCS/ftokens.w,v pretzel/ftokens/RCS/ftparse.nw,v pretzel/ftokens/RCS/ftscan.l,v pretzel/ftokens/RCS/Makefile,v pretzel/ftokens/RCS/ftparse.y,v pretzel/ftokens/RCS/ftscan.nw,v pretzel/doc/pretzelbook/RCS pretzel/doc/pretzelbook/RCS/pretzelbook.tex,v pretzel/doc/project.report/RCS pretzel/doc/project.report/RCS/report-intro.tex,v pretzel/doc/project.report/RCS/chap3.tex,v pretzel/doc/project.report/RCS/appendix.tex,v pretzel/doc/project.report/RCS/chap5.tex,v pretzel/doc/project.report/RCS/chap2.tex,v pretzel/doc/project.report/RCS/abstract.tex,v pretzel/doc/project.report/RCS/report.tex,v pretzel/doc/project.report/RCS/Makefile,v pretzel/doc/project.report/RCS/manual.tex,v pretzel/doc/project.report/RCS/chap4.tex,v pretzel/doc/project.report/RCS/chap1.tex,v pretzel/doc/project.report/RCS/manual-intro.tex,v pretzel/doc/project.report/RCS/acknowledge.tex,v pretzel/doc/project.report/RCS/manual-title.tex,v pretzel/doc/styles/RCS pretzel/doc/styles/RCS/pretzel-noweb-style.nw,v pretzel/doc/styles/RCS/pretzel-latex.sty,v pretzel/doc/styles/RCS/pretzeldoc.sty,v pretzel/doc/styles/RCS/pretzel.sty,v pretzel/doc/RCS pretzel/doc/RCS/ADDENDUM,v pretzel/attr/RCS pretzel/attr/RCS/attrtest.w,v pretzel/attr/RCS/attr.spc,v pretzel/attr/RCS/Makefile,v pretzel/attr/RCS/attrtest.nw,v pretzel/attr/RCS/attr.w,v pretzel/attr/RCS/attr.nw,v pretzel/languages/examples/RCS pretzel/languages/examples/RCS/small-example.simpas,v pretzel/languages/examples/RCS/simpas.fg,v pretzel/languages/examples/RCS/simpas.ft,v pretzel/languages/examples/RCS/Makefile,v pretzel/languages/examples/RCS/example-frame.tex,v pretzel/languages/pascal/RCS pretzel/languages/pascal/RCS/nice.pas,v pretzel/languages/pascal/RCS/frame.tex,v pretzel/languages/pascal/RCS/multiple.nw,v pretzel/languages/pascal/RCS/pascal.fg,v pretzel/languages/pascal/RCS/pascal.ft,v pretzel/languages/pascal/RCS/gauss.pas,v pretzel/languages/pascal/RCS/Makefile,v pretzel/languages/pascal/RCS/t.c,v pretzel/languages/pascal/RCS/ml.pas,v pretzel/languages/pascal/RCS/wurzel.pas,v pretzel/languages/pascal/RCS/README,v pretzel/languages/pascal/RCS/pprinted.tex,v pretzel/languages/cee/RCS pretzel/languages/cee/RCS/complex-example.c,v pretzel/languages/cee/RCS/fullexample.tex,v pretzel/languages/cee/RCS/Makefile,v pretzel/languages/cee/RCS/cee.fg,v pretzel/languages/cee/RCS/cee.ft,v pretzel/languages/cee/RCS/example.c,v pretzel/contrib/leew/RCS pretzel/contrib/leew/RCS/java.ft,v pretzel/contrib/leew/RCS/leew-original-source pretzel/contrib/leew/RCS/Makefile,v pretzel/contrib/leew/RCS/pp-java.sty,v pretzel/contrib/leew/RCS/support.nw,v pretzel/contrib/leew/RCS/java.fg,v pretzel/contrib/leew/RCS/jtest.nw,v pretzel/contrib/leew/RCS/totex.nw,v pretzel/contrib/leew/RCS/README,v pretzel/contrib/noweb/general/RCS pretzel/contrib/noweb/general/RCS/strsave.nw,v pretzel/contrib/noweb/general/RCS/columns.nw,v pretzel/contrib/noweb/general/RCS/testcode.nw,v pretzel/contrib/noweb/general/RCS/test.ft,v pretzel/contrib/noweb/general/RCS/pretty.nw,v pretzel/contrib/noweb/general/RCS/Makefile,v pretzel/contrib/noweb/general/RCS/test.fg,v pretzel/contrib/noweb/general/RCS/nowebpretzelpp.nw,v pretzel/contrib/noweb/general/RCS/match.nw,v pretzel/contrib/noweb/general/RCS/errors.nw,v pretzel/contrib/noweb/general/RCS/README,v pretzel/contrib/noweb/general/RCS/getline.nw,v pretzel/contrib/noweb/cee.html/RCS pretzel/contrib/noweb/cee.html/RCS/cee2htmltest.nw,v pretzel/contrib/noweb/cee.html/RCS/cee2html.ft,v pretzel/contrib/noweb/cee.html/RCS/cee2html.fg,v pretzel/contrib/noweb/cee.html/RCS/prettycee2html.nw,v pretzel/contrib/noweb/cee.html/RCS/Makefile,v pretzel/contrib/noweb/cee.latex/RCS pretzel/contrib/noweb/cee.latex/RCS/ceetest.nw,v pretzel/contrib/noweb/cee.latex/RCS/c.ft,v pretzel/contrib/noweb/cee.latex/RCS/Makefile,v pretzel/contrib/noweb/cee.latex/RCS/cee.fg,v pretzel/contrib/noweb/cee.latex/RCS/c.fg,v pretzel/contrib/noweb/cee.latex/RCS/cee.ft,v pretzel/contrib/noweb/cee.latex/RCS/README,v pretzel/contrib/noweb/java.latex/RCS pretzel/contrib/noweb/java.latex/RCS/javafx.fg,v pretzel/contrib/noweb/java.latex/RCS/javafx.ft,v pretzel/RCS pretzel/RCS/Makefile,v pretzel/RCS/README,v pretzel/output/RCS pretzel/output/RCS/outtest.w,v pretzel/output/RCS/blankoutput.nw,v pretzel/output/RCS/output.w,v pretzel/output/RCS/Makefile,v pretzel/output/RCS/outtest.nw,v pretzel/output/RCS/asciioutput.nw,v pretzel/output/RCS/output.nw,v pretzel/output/RCS/output.spc,v pretzel/fgrammar/RCS pretzel/fgrammar/RCS/fgscan.spc,v pretzel/fgrammar/RCS/fgscan.l,v pretzel/fgrammar/RCS/fgparse.spc,v pretzel/fgrammar/RCS/pparse.spc,v pretzel/fgrammar/RCS/fgparse.nw,v pretzel/fgrammar/RCS/fgrammar.nw,v pretzel/fgrammar/RCS/Makefile,v pretzel/fgrammar/RCS/fgparse.y,v pretzel/fgrammar/RCS/fgrammar.w,v pretzel/fgrammar/RCS/fgscan.nw,v pretzel/pretzel-it/RCS pretzel/pretzel-it/RCS/Makefile,v pretzel/pretzel-it/RCS/pretzel-it,v pretzel/man/RCS pretzel/man/RCS/pretzel.1,v pretzel/man/RCS/pretzel-it.1,v pretzel/man/RCS/Makefile,v pretzel/main/RCS pretzel/main/RCS/pretzel.nw,v pretzel/main/RCS/Makefile,v pretzel/main/RCS/plaindpp.c,v pretzel/main/RCS/pretzel.w,v pretzel/main/RCS/plainpp.c,v pretzel-2.0n-2/alloca.c0000644000000000000000000001302406014152457013456 0ustar rootroot/* alloca -- (mostly) portable public-domain implementation -- D A Gwyn last edit: 86/05/30 rms include config.h, since on VMS it renames some symbols. Use xmalloc instead of malloc. This implementation of the PWB library alloca() function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. It should work under any C implementation that uses an actual procedure stack (as opposed to a linked list of frames). There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca()-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ /* * $Revision: 1.3 $ * $Source: /import/kaplan/stable/distrib/epoch-4.0p0/src/RCS/alloca.c,v $ * $Date: 92/02/23 11:02:58 $ * $Author: love $ */ #ifndef LINT static char rcsid[] = "$Author: love $ $Date: 92/02/23 11:02:58 $ $Source: /import/kaplan/stable/distrib/epoch-4.0p0/src/RCS/alloca.c,v $ $Revision: 1.3 $"; #endif #ifdef emacs #include "config.h" #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif static #endif emacs #ifndef alloca /* If using GCC, this file's not needed. */ #ifdef __STDC__ typedef void *pointer; /* generic pointer type */ #else typedef char *pointer; /* generic pointer type */ #endif #define NULL 0 /* null pointer constant */ extern void free(); extern pointer malloc(); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /********* STACK_DIRECTION SET ********/ #ifdef __MSDOS__ #define STACK_DIRECTION -1 /* grows downward */ #endif #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* direction unknown */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* known at compile-time */ #else /* STACK_DIRECTION == 0; need run-time code */ static int stack_dir; /* 1 or -1 once known */ #define STACK_DIR stack_dir static void find_stack_direction (/* void */) { static char *addr = NULL; /* address of first `dummy', once known */ auto char dummy; /* to get stack address */ if (addr == NULL) { /* initial entry */ addr = &dummy; find_stack_direction (); /* recurse once */ } else /* second entry */ if (&dummy > addr) stack_dir = 1; /* stack grew upward */ else stack_dir = -1; /* stack grew downward */ } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca()ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc() alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* to force sizeof(header) */ struct { union hdr *next; /* for chaining headers */ char *deep; /* for stack depth measure */ } h; } header; /* alloca( size ) returns a pointer to at least `size' bytes of storage which will be automatically reclaimed upon exit from the procedure that called alloca(). Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ static header *last_alloca_header = NULL; /* -> last alloca header */ pointer alloca (size) /* returns pointer to storage */ unsigned size; /* # bytes to allocate */ { auto char probe; /* probes stack depth: */ register char *depth = &probe; #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* unknown growth direction */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca()ed storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* traverses linked list */ for (hp = last_alloca_header; hp != NULL;) if (STACK_DIR > 0 && hp->h.deep > depth || STACK_DIR < 0 && hp->h.deep < depth) { register header *np = hp->h.next; free ((pointer) hp); /* collect garbage */ hp = np; /* -> next header */ } else break; /* rest are not deeper */ last_alloca_header = hp; /* -> last valid storage */ } if (size == 0) return NULL; /* no allocation required */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* address of header */ ((header *)new)->h.next = last_alloca_header; ((header *)new)->h.deep = depth; last_alloca_header = (header *)new; /* User storage begins just after header. */ return (pointer)((char *)new + sizeof(header)); } } #endif /* no alloca */