Index: tools/prettyprinter/filter.cc
===================================================================
--- tools/prettyprinter/filter.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/filter.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,241 @@
+//                              -*- Mode: C++ -*- 
+// 
+// Pretty Printer, Copyright (C) Peter A. Buhr 2002
+// 
+// filter.cc -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Tue Apr  9 22:33:44 2002
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Dec 17 11:25:50 2002
+// Update Count     : 60
+// 
+
+#include "filter.h"
+#include "yacc.tab.h" 
+
+
+void (*filter)( Token *tree ) = 0;
+
+
+void freeTree( Token *tree ) {				// postfix tree traversal
+    if ( tree == NULL ) return;
+    if ( tree->down != NULL ) freeTree( tree->down );
+    if ( tree->left != NULL ) freeTree( tree->left );
+    //cerr << "free token: \"" << tree->getText() << "\" : " << tree->getKind() << endl;
+    delete tree;
+} // freeTree
+
+
+void Identity( Token *tree ) {				// prefix tree traversal
+    if ( tree == NULL ) return;
+    // print only the terminals
+    if ( tree->isTerminal() ) cout << tree->getWS() << tree->getText();
+    if ( tree->down != NULL ) Identity( tree->down );
+    if ( tree->left != NULL ) Identity( tree->left );
+} // Identity
+
+
+static void Parse_Tree1( Token *tree, int indent ) {	// prefix tree traversal
+    cout << string( indent, ' ' );
+    if ( tree->isTerminal() ) {				// terminals
+	cout << "\"" << tree->getText() << "\"";
+    } else {						// non-terminals
+	cout << tree->getText();
+    } // if
+    cout << " : " << tree->getKind()
+	 //<< " \"" << tree->getWS() << " \""
+	 << endl;
+    if ( tree->down != NULL ) Parse_Tree1( tree->down, indent + 2 );
+    if ( tree->left != NULL ) Parse_Tree1( tree->left, indent );
+} // Parse_Tree1
+
+void Parse_Tree( Token *tree ) {
+    if ( tree == NULL ) return;
+    Parse_Tree1( tree, 0 );
+} // Parse_Tree
+
+
+void Nocode( Token *tree ) {				// prefix tree traversal
+    static bool declprt = true;
+    if ( tree == NULL ) return;
+
+    if ( tree->isTerminal() ) {				// terminals
+	cout << tree->getWS() << tree->getText();
+    } else {						// non-terminals
+	switch ( tree->getKind() ) {
+	  case _RHS: {
+	      int first = 0;				// first RHS after ':' or '|' treated specially
+	      int push = 0, pop = 0;
+	      for ( Token *i = tree->down; i != 0; i = i->left ) {
+		  switch ( i->getKind() ) {
+		    case _ACTION:
+		      cout << string( (push * 4 + pop * 3) / 7, '\t' );
+		      push = pop = 0;
+		      cout << i->down->getComment();	// ignore code but print its comment, if any
+		      break;
+		    case _PREC:
+		      Nocode( i->down );		// print verbatim
+		      break;
+		    case '|':				// start of alternative and special case
+		      first = 0;
+		    case ';':				// print with whitespace
+		      cout << string( (push * 4 + pop * 3) / 7, '\t' );
+		      push = pop = 0;
+		      cout << i->getWS() << i->getText();
+		      break;
+		    default:
+		      if ( i->getKind() == IDENTIFIER ) {
+			  if ( i->getText() == "push" ) {
+			      push += 1;
+			      if ( first == 0 ) {	// first RHS after ':' or '|' ?
+				  cout << i->getComment(); // ignore rhs but print its comment, if any
+			      } // if 
+			      break;
+			  } else if ( i->getText() == "pop" ) {
+			      pop += 1;
+			      if ( first == 0 ) {	// first RHS after ':' or '|' ?
+				  cout << i->getComment(); // ignore rhs but print its comment, if any
+			      } // if 
+			      break;
+			  } // if
+		      } // if
+		      // If there is a comment or this is the first RHS after
+		      // ':' or '|', then include the whitespace before the
+		      // token. Otherwise, fold the token onto the same line
+		      // separated with a blank.
+		      string t1( i->getText() );
+		      if ( i->isComment() || first == 0 ) {
+			  first = t1.length();
+			  cout << i->getWS() << t1;
+		      } else {
+			  if ( first + t1.length() <= 100 ) { // check for long lines during folding
+			      first += t1.length();
+			      cout << " " << t1;
+			  } else {
+			      first = t1.length();
+			      cout << endl << "\t\t\t\t" << t1;
+			  } // if
+		      } // if
+		  } // switch
+	      } // for
+	      break;
+	  }
+	  case _LITERALBLOCK:				// ignore code but print its comment, if any
+	    cout << tree->down->getComment();
+	    break;
+	  case _DECLARATION: {				// ignore certain declarations
+	      int kind = tree->down->getKind();		// get kind of declaration
+	      if ( kind != UNION && kind != TYPE ) {
+		  declprt = true;
+		  Nocode( tree->down );			// print verbatim
+	      } else if ( declprt ) {			// ignore declaration but print its comment, if any
+		  declprt = false;
+		  cout << tree->down->getComment();
+	      } // if
+	      break;
+	  }
+	  case _USERSECTION_OPT:			// ignore but add newline at the end
+	    cout << endl;
+	    break;
+	  default:
+	    if ( tree->down != NULL ) Nocode( tree->down );
+	} // switch
+    } // if
+    if ( tree->left != NULL ) Nocode( tree->left );
+} // Nocode
+
+
+void LaTeX( Token *tree ) {				// prefix tree traversal
+    if ( tree == NULL ) return;
+
+    if ( tree->isTerminal() ) {				// terminals
+	cout << tree->getWS() << tree->getText();
+	if ( tree->getKind() == IDENTIFIER ) {
+	    string id( tree->getText() );
+	    cout << "\\(\\index{" << id << "@\\protect\\LGbegin\\protect\\lgrinde\\)" << id << "\\(\\protect\\endlgrinde\\protect\\LGend{}}\\)";
+	} // if
+    } else {						// non-terminals
+	switch ( tree->getKind() ) {
+	  case _RHS: {
+	      int first = 0;				// first RHS after ':' or '|' treated specially
+	      int push = 0, pop = 0;
+	      Token *prev = 0;
+	      for ( Token *i = tree->down; i != 0; prev = i, i = i->left ) {
+		  switch ( i->getKind() ) {
+		    case _ACTION:
+		      cout << i->down->getComment();	// ignore code but print its comment, if any
+		      break;
+		    case _PREC:
+		      LaTeX( i->down );			// print verbatim
+		      break;
+		    case '|':				// start of alternative and special case
+		      first = 0;
+		      push = pop = 0;
+		    case ';':				// print with whitespace
+		      cout << i->getWS() << i->getText();
+		      break;
+		    default:
+		      if ( i->getKind() == IDENTIFIER ) {
+			  if ( i->getText() == "push" ) {
+			      push += 1;
+			      break;
+			  } else if ( i->getText() == "pop" ) {
+			      pop += 1;
+			      break;
+			  } // if
+		      } // if
+		      // If there is a comment or this is the first RHS after
+		      // ':' or '|', then include the whitespace before the
+		      // token. Otherwise, fold the token onto the same line
+		      // separated with a blank.
+		      string t1( i->getText() );
+		      if ( i->isComment() || first == 0 ) {
+			  first = t1.length();
+			  cout << i->getWS() << t1;
+			  if ( i->getKind() == IDENTIFIER ) {
+			      string id( tree->getText() );
+			      cout << "\\(\\index{" << id << "@\"\\verb=" << id << "=}\\)";
+			  } // if
+		      } else {
+			  if ( first + t1.length() <= 100 ) { // check for long lines during folding
+			      first += t1.length();
+			      cout << " " << t1;
+			  } else {
+			      first = t1.length();
+			      cout << endl << "\t\t\t\t" << t1;
+			  } // if
+		      } // if
+		  } // switch
+	      } // for
+	      break;
+	  }
+	  case _LITERALBLOCK:				// ignore code but print its comment, if any
+	    cout << tree->down->getComment();
+	    break;
+	  case _DECLARATION: {				// ignore certain declarations
+	      int kind = tree->down->getKind();	// get kind of declaration
+	      if ( kind != UNION && kind != TYPE ) {
+		  LaTeX( tree->down );		// print verbatim
+	      } // if
+	      break;
+	  }
+	  case _USERSECTION_OPT:			// ignore but add newline at the end
+	    cout << endl;
+	    break;
+	  default:
+	    if ( tree->down != NULL ) LaTeX( tree->down );
+	} // switch
+    } // if
+    if ( tree->left != NULL ) LaTeX( tree->left );
+} // LaTeX
+
+
+void HTML( Token *tree ) {				// prefix tree traversal
+    cerr << "ERROR: html style not implemented" << endl;
+} // HTML
+
+
+// Local Variables: //
+// compile-command: "gmake" //
+// End: //
Index: tools/prettyprinter/filter.h
===================================================================
--- tools/prettyprinter/filter.h	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/filter.h	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,34 @@
+//                              -*- Mode: C++ -*- 
+// 
+// Pretty Printer, Copyright (C) Peter A. Buhr 2002
+// 
+// filter.h -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Tue Apr  9 22:31:18 2002
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Apr  9 22:35:55 2002
+// Update Count     : 2
+// 
+
+#ifndef __FILTER_H__
+#define __FILTER_H__
+
+#include "parse.h"
+
+
+extern void (*filter)( Token *tree );			// pointer to filter for parse tree
+void freeTree( Token *tree );				// free storage for parse tree
+
+void Identity( Token *tree );				// parse-tree filters
+void Parse_Tree( Token *tree );
+void Nocode( Token *tree );
+void LaTeX( Token *tree );
+void HTML( Token *tree );
+
+#endif /* __FILTER_H__ */
+
+
+// Local Variables: //
+// compile-command: "gmake" //
+// End: //
Index: tools/prettyprinter/lex.l
===================================================================
--- tools/prettyprinter/lex.l	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/lex.l	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,169 @@
+/*                               -*- Mode: C -*- 
+ * 
+ * Pretty Printer Lexer, Copyright (C) Rodolfo Gabriel Esteves and Peter A. Buhr 2001
+ *      Permission is granted to copy this grammar and to use it within software systems.
+ *      THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+ * 
+ * lex.l -- 
+ * 
+ * Author           : Rodolfo Gabriel Esteves
+ * Created On       : Sat Dec 15 11:45:59 2001
+ * Last Modified By : Peter A. Buhr
+ * Last Modified On : Mon Apr  8 15:48:24 2002
+ * Update Count     : 245
+ */
+
+%option stack
+%option yylineno
+
+%{
+#include <list>
+#include <string>
+#include <iostream>
+
+#include "parse.h" 
+#include "yacc.tab.h" 
+
+#define RETURN_TOKEN( kind ) yylval.tokenp = new Token( yytext, ws_list, kind ); return kind;
+
+list<string> ws_list;
+string comment_str;
+string code_str;
+%}
+
+integer [0-9]+
+identifier [a-zA-Z_$][0-9a-zA-Z_$]*
+
+simple_escape ['"?\\]
+escape_sequence [\\]{simple_escape}
+c_char [^'\\\n]|{escape_sequence}
+s_char [^"\\\n]|{escape_sequence}
+
+%x C_COMMENT STR C_CODE
+
+/* ---------------------------- Token Section ---------------------------- */
+%%
+<INITIAL,C_CODE>"/*"	{				/* C style comments */
+			#if defined(DEBUG_ALL) | defined(DEBUG_COMMENT)
+    			    cerr << "\"/*\" : " << yytext << endl;
+			#endif
+			    if ( YYSTATE == C_CODE ) code_str += yytext;
+			    else comment_str += yytext;
+			    yy_push_state(C_COMMENT);
+			}
+<C_COMMENT>(.|"\n")	{				/* C style comments */
+			#if defined(DEBUG_ALL) | defined(DEBUG_COMMENT)
+    			    cerr << "<C_COMMENT>(.|\\n) : " << yytext << endl;
+			#endif
+			    if ( yy_top_state() == C_CODE ) code_str += yytext;
+			    else comment_str += yytext;
+			}
+<C_COMMENT>"*/"		{				/* C style comments */
+			#if defined(DEBUG_ALL) | defined(DEBUG_COMMENT)
+    			    cerr << "<C_COMMENT>\"*/\" : " << yytext << endl;
+			#endif
+			    if ( yy_top_state() == C_CODE ) code_str += yytext;
+			    else {
+				comment_str += yytext;
+				//cerr << "C COMMENT : " << endl << comment_str << endl;
+				ws_list.push_back( comment_str );
+				comment_str = "";
+			    }
+			    yy_pop_state();
+			}
+<INITIAL,C_CODE>"//"[^\n]*"\n" {			/* C++ style comments */
+			#if defined(DEBUG_ALL) | defined(DEBUG_COMMENT)
+    			    cerr << "\"//\"[^\\n]*\"\n\" : " << yytext << endl;
+			#endif
+			    if ( YYSTATE == C_CODE ) code_str += yytext;
+			    else {
+				comment_str += yytext;
+				//cerr << "C++ COMMENT : " << endl << comment_str << endl;
+				ws_list.push_back( comment_str );
+				comment_str = "";
+			    }
+			}
+
+";"			{ RETURN_TOKEN( ';' ) }
+":"			{ RETURN_TOKEN( ':' ) }
+"|"			{ RETURN_TOKEN( '|' ) }
+","			{ RETURN_TOKEN( ',' ) }
+"<"			{ RETURN_TOKEN( '<' ) }
+">"			{ RETURN_TOKEN( '>' ) }
+
+[[:space:]]+		{				/* [ \t\n]+ */
+			    ws_list.push_back( yytext );
+			    //cerr << "WS : " << "\"" << yytext << "\"" << endl;
+			}
+
+<INITIAL>"{"		{ RETURN_TOKEN( '{' ) }
+<INITIAL>"}"		{ RETURN_TOKEN( '}' ) }
+<C_CODE>"{"		{
+			#if defined(DEBUG_ALL) | defined(DEBUG_C)
+			    cerr << "<C_CODE>. : " << yytext << endl;
+			#endif
+			    code_str += yytext;
+			    RETURN_TOKEN( '{' )
+			}
+<C_CODE>"}"		{
+			#if defined(DEBUG_ALL) | defined(DEBUG_C)
+			    cerr << "<C_CODE>. : " << yytext << endl;
+			#endif
+			    code_str += yytext;
+			    RETURN_TOKEN( '}' )
+			}
+
+"%%"			{ RETURN_TOKEN( MARK ) }
+"%{"			{ RETURN_TOKEN( LCURL ) }
+<C_CODE>"%}"		{ RETURN_TOKEN( RCURL ) }
+
+^"%union"       	{ RETURN_TOKEN( UNION ) }
+^"%start"       	{ RETURN_TOKEN( START ) }
+^"%token"       	{ RETURN_TOKEN( TOKEN ) }
+^"%type"	       	{ RETURN_TOKEN( TYPE ) }
+^"%left"	       	{ RETURN_TOKEN( LEFT ) }
+^"%right"	       	{ RETURN_TOKEN( RIGHT ) }
+^"%nonassoc"    	{ RETURN_TOKEN( NONASSOC ) }
+^"%pure_parser"    	{ RETURN_TOKEN( PURE_PARSER ) }
+^"%semantic_parser"    	{ RETURN_TOKEN( SEMANTIC_PARSER ) }
+^"%expect"  	  	{ RETURN_TOKEN( EXPECT ) }
+^"%thong" 	   	{ RETURN_TOKEN( THONG ) }
+
+"%prec" 	   	{ RETURN_TOKEN( PREC ) }
+
+{integer}	    	{ RETURN_TOKEN( INTEGER ); }
+[']{c_char}[']    	{ RETURN_TOKEN( CHARACTER ); }
+{identifier}    	{ RETURN_TOKEN( IDENTIFIER ); }
+
+<C_CODE>["]{s_char}*["]	{				/* hide braces "{}" in strings */
+			#if defined(DEBUG_ALL) | defined(DEBUG_C)
+			    cerr << "<C_CODE>. : " << yytext << endl;
+			#endif
+			    code_str += yytext;
+			}
+
+<C_CODE>(.|\n)		{				/* must be last rule of C_CODE */
+			#if defined(DEBUG_ALL) | defined(DEBUG_C)
+			    cerr << "<C_CODE>. : " << yytext << endl;
+			#endif
+			    code_str += yytext;
+			}
+
+.			{ printf("UNKNOWN CHARACTER:%s\n", yytext); } /* unknown characters */
+%%
+void lexC(void) {
+    BEGIN(C_CODE);
+}
+
+string lexYacc(void) {
+    BEGIN(INITIAL);
+    //cerr << "CODE: " << endl << code_str << endl;
+    string temp( code_str );
+    code_str = "";
+    return temp;
+}
+
+/* Local Variables: */
+/* fill-column: 100 */
+/* compile-command: "gmake" */
+/* End: */
Index: tools/prettyprinter/main.cc
===================================================================
--- tools/prettyprinter/main.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/main.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,40 @@
+#include <cstdlib>
+#include "filter.h"
+
+extern int yydebug;
+extern int yyparse( void );
+
+int main( int argc, char *argv[] ) {
+    switch ( argc ) {
+      case 2: {
+	  string arg( argv[1] );
+
+	  if ( arg == "-identity" ) {
+	      filter = Identity;
+	  } else if ( arg == "-parse_tree" ) {
+	      filter = Parse_Tree;
+	  } else if ( arg == "-nocode" ) {
+	      filter = Nocode;
+	  } else if ( arg == "-latex" ) {
+	      filter = LaTeX;
+	  } else if ( arg == "-html" ) {
+	      filter = HTML;
+	  } else {
+	      cerr << "Unknown printer option: " << argv[1] << endl;
+	      goto usage;
+	  } // if
+	  break;
+      }
+      usage:
+      default:
+	cerr << "Usage: " << argv[0] << " [-identity | -parse_tree | -nocode | -latex | -html] < bison.y" << endl;
+	exit( -1 );
+    }
+
+    //yydebug = 1;
+    yyparse();
+}
+
+// Local Variables: //
+// compile-command: "gmake" //
+// End: //
Index: tools/prettyprinter/parse.cc
===================================================================
--- tools/prettyprinter/parse.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/parse.cc	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,94 @@
+//                              -*- Mode: C++ -*- 
+// 
+// Pretty Printer, Copyright (C) Richard C. Bilson and Rodolfo G. Esteves 2001
+// 
+// parse.cc -- 
+// 
+// Author           : Richard C. Bilson and Rodolfo G. Esteves
+// Created On       : Sun Dec 16 15:06:31 2001
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Apr  9 22:38:19 2002
+// Update Count     : 435
+// 
+
+#include "parse.h"
+#include "filter.h"
+#include "yacc.tab.h" 
+
+
+Token::Token( const string &text, int kind ) : text(text), kind(kind) {
+    left = down = NULL;
+} // Token::Token
+
+Token::Token( const string &text, list<string> &ws_list, int kind ) : text(text), kind(kind) {
+//    cerr << "Token3 : text \"" << text << "\"";
+//    for ( list<string>::iterator i = ws_list.begin(); i != ws_list.end(); i ++ ) {
+//	cerr << " WSt: \"" << *i << "\"";
+//    }
+//    cerr << endl;
+    left = down = NULL;
+    // O(1) transfer of the current lex whitespace list to the token's
+    // whitespace list, and clearing the lex whitespace list.
+    Token::ws_list.splice( Token::ws_list.end(), ws_list );
+} // Token::Token
+
+void Token::addLeftTail( Token *n ) {
+    Token *p = this;
+    while ( p->left != 0 ) {
+	p = p->left;
+    } // while
+    p->left = n;
+} // Token::addLeftTail
+
+void Token::addDownLeftTail( Token *n ) {
+    if ( down == 0 ) {
+	down = n;
+    } else {
+	down->addLeftTail( n );
+    } // if
+} // Token::addDownLeftTail
+
+bool Token::isTerminal() {
+    return kind < END_TERMINALS;
+} // Token::isTerminal
+
+int Token::getKind() const {
+    return kind;
+} // Token::getKind()
+
+string Token::getText() const {
+    return text;
+} // Token::getText()
+
+string Token::getWS() {
+    string ret;
+    // concatenate whitespace and comment text
+    for ( list<string>::iterator i = ws_list.begin(); i != ws_list.end(); i ++ ) {
+	ret += *i;
+    } // for
+    return ret;
+} // Token::getWS
+
+bool Token::isComment() {
+    return ws_list.size() > 1 || ( ws_list.size() == 1 && (*ws_list.begin())[0] == '/' );
+} // Token::isComment
+
+string Token::getComment() {
+    string ret;
+    // concatenate whitespace and comment text up to the last comment
+    if ( ws_list.size() > 1 ) {
+	list<string>::iterator end = -- ws_list.end();
+	if ( (*end)[0] == '/' ) end ++;
+	for ( list<string>::iterator i = ws_list.begin(); i != end; i ++ ) {
+	    ret += *i;
+	} // for
+    } else if ( ws_list.size() == 1 ) {
+	if ( (*ws_list.begin())[0] == '/' ) ret = *ws_list.begin();
+    } // if
+    return ret;
+} // Token::getComment
+
+
+// Local Variables: //
+// compile-command: "gmake" //
+// End: //
Index: tools/prettyprinter/parse.h
===================================================================
--- tools/prettyprinter/parse.h	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/parse.h	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,57 @@
+//                              -*- Mode: C++ -*- 
+// 
+// Pretty Printer, Copyright (C) Richard C. Bilson and Rodolfo G. Esteves 2001
+// 
+// parse.h - Various declarations that are needed so that the generated parser
+//           and lexer compile with C++, and to share information between the
+//           parser, lexer, and driver program
+// 
+// Author           : Richard C. Bilson and Rodolfo G. Esteves
+// Created On       : Sun Dec 16 15:00:49 2001
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Dec 17 10:55:31 2002
+// Update Count     : 163
+// 
+
+#ifndef __PARSE_H__
+#define __PARSE_H__
+
+#define YYDEBUG_LEXER_TEXT( yylval )			// lexer loads this up each time
+#define YYDEBUG 1					// get the pretty debugging code to compile
+
+int yylex();
+
+#include <iostream>
+#include <string>
+#include <list>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+using std::list;
+
+struct Token {
+    string text;					// text of terminal or non-terminal token
+    int kind;						// kind of terminal or non-terminal token
+    list<string> ws_list;				// list of whitespace and comments before terminal token
+    Token *left, *down;					// binary parse tree links
+
+    Token( const string &, int );
+    Token( const string &, list<string> &, int );
+    void addLeftTail( Token * );
+    void addDownLeftTail( Token * );
+    bool isTerminal();
+    int getKind() const;
+    string getText() const;
+    string getWS();
+    bool isComment();
+    string getComment();
+};
+
+#endif /* __PARSE_H__ */
+
+
+// Local Variables: //
+// compile-command: "gmake" //
+// End: //
Index: tools/prettyprinter/test.tex
===================================================================
--- tools/prettyprinter/test.tex	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/test.tex	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,14 @@
+\documentclass[11pt]{article}
+\usepackage{fullpage,times,lgrind}
+
+\begin{document}
+
+\lgrindfile{bison}
+
+\end{document}
+
+% Local Variables: %
+% tab-width: 4 %
+% fill-column: 100 %
+% compile-command: "pdflatex test.tex" %
+% End: %
Index: tools/prettyprinter/test.y
===================================================================
--- tools/prettyprinter/test.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/test.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,48 @@
+/* adasd1 */   
+
+%token<tokenp>	A 1 , B 2 C 3			// %%
+%type<tokenp>	A , B C				// %%
+%type	A , B C				// %%
+
+/* adsad2 */
+
+%%
+
+rules2	: pop xxx %prec '.' yyy push %prec '.'	/* XX */
+		{ $$ = build_nt (CALL_EXPR, $1, $2, NULL_TREE); }
+		{ $$ = build_nt (CALL_EXPR, $1, $2, NULL_TREE); }
+	| xxx yyy ';'
+	;
+
+rules1	: /* empty */
+	| xxx
+	  /* fred */ yyy
+	| xxx
+		{}
+	  yyy ';'
+	|
+	;
+
+mark		: MARK
+		| error					/* missing %% */
+			{
+			    cerr << "no input grammar, missing %% mark" << endl;
+			    exit( -1 );
+			}
+		;
+
+x	: xxx yyy
+
+y	:
+	;
+
+w	:
+	  xxx
+	|
+	  yyy
+	;
+%%
+{
+    {
+    }
+}
Index: tools/prettyprinter/test1.y
===================================================================
--- tools/prettyprinter/test1.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/test1.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,24 @@
+%token A
+
+%start rules
+%%
+rules	: /* empty */		/* no rules */
+	| lhs rhs		/* start new rule */
+	| lhs rhs ';'		/* start new rule */
+	|
+	;
+
+lhs	: A | ':' ;
+
+rhs	: /* empty */		/* empty rule */
+        | rhs more ;
+
+more	: lhs			/* start next rule */
+	| ';' lhs		/* start next rule */
+	| foo			/* component of current rule */
+	| '|'			/* empty rule */
+	;
+
+foo	: A | 'l' | 'X'
+
+bar:
Index: tools/prettyprinter/yacc.y
===================================================================
--- tools/prettyprinter/yacc.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
+++ tools/prettyprinter/yacc.y	(revision fda816874a6a323b57c9ce0409b20c6c3ddea4cf)
@@ -0,0 +1,481 @@
+/*                               -*- Mode: C -*- 
+ * 
+ *  Pretty Printer, Copyright (C) Rodolfo G. Esteves and Peter A. Buhr 2001
+ *      Permission is granted to copy this grammar and to use it within software systems.
+ *      THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+ * 
+ * yacc.y -- 
+ * 
+ * Author           : Rodolfo G. Esteves
+ * Created On       : Sat Dec 15 13:44:21 2001
+ * Last Modified By : Peter A. Buhr
+ * Last Modified On : Mon Jun 27 21:51:06 2016
+ * Update Count     : 1028
+ */
+
+%{
+#include <stdio.h>
+#include "parse.h"
+#include "filter.h"
+
+#define YYDEBUG 1			// get the pretty debugging code to compile
+
+extern list<string> ws_list;		// lex variable containing accumulated whitespace
+void lexC( void );
+string lexYacc( void );
+
+void yyerror( char *s ) {
+    extern int yylineno;
+
+    cerr << "Error in line: " << yylineno << ": " << s << endl;
+    return;
+}
+
+Token *declstart;
+Token *rulestart;
+Token *nameliststart;
+%}
+
+%union {
+    Token *tokenp;
+}
+
+%token<tokenp>	','
+%token<tokenp>	'<'
+%token<tokenp>	'>'
+%token<tokenp>	'{'
+%token<tokenp>	'}'
+%token<tokenp>	':'
+%token<tokenp>	';'
+%token<tokenp>	'|'
+
+%token<tokenp>	MARK			// %%
+%token<tokenp>	LCURL			// %{
+%token<tokenp>	RCURL			// %}
+
+%token<tokenp>	INTEGER			// integer constant
+%token<tokenp>	CHARACTER		// character constant
+%token<tokenp>	IDENTIFIER		// identifier
+%token<tokenp>	CODE			// C code
+
+%token<tokenp>	START			// %start
+%token<tokenp>	UNION			// %union
+%token<tokenp>	TOKEN			// %token
+%token<tokenp>	LEFT			// %left
+%token<tokenp>	RIGHT			// %right
+%token<tokenp>	NONASSOC		// %nonassoc
+%token<tokenp>	TYPE			// %type
+%token<tokenp>	PURE_PARSER		// %pure_parser
+%token<tokenp>	SEMANTIC_PARSER		// %semantic_parser
+%token<tokenp>	EXPECT			// %expect
+%token<tokenp>	THONG			// %thong
+
+%token<tokenp>	PREC			// %prec
+
+%token		END_TERMINALS		// ALL TERMINAL TOKEN NAMES MUST APPEAR BEFORE THIS
+
+%type<tokenp>	sections
+%token		_SECTIONS
+%type<tokenp>	mark
+%type<tokenp>	defsection_opt
+%token		_DEFSECTION_OPT
+%type<tokenp>	declarations
+%type<tokenp>	literalblock
+%token		_LITERALBLOCK
+%type<tokenp>	declaration
+%token		_DECLARATION
+%type<tokenp>	union
+%type<tokenp>	rword
+%type<tokenp>	tag_opt
+%token		_TAG_OPT
+%type<tokenp>	namenolist
+%token		_NAMENOLIST
+%type<tokenp>	nameno
+%token		_NAMENO
+%type<tokenp>	namelist
+%token		_NAMELIST
+%type<tokenp>	name
+%type<tokenp>	rulesection
+%token		_RULESECTION
+%type<tokenp>	rules
+%token		_RULE
+%type<tokenp>	lhs
+%token		_LHS
+%type<tokenp>	rhs
+%token		_RHS
+%type<tokenp>	prod
+%type<tokenp>	prec
+%token		_PREC
+%type<tokenp>	action
+%token		_ACTION
+%type<tokenp>	usersection_opt
+%token		_USERSECTION_OPT
+%type<tokenp>	ccode_opt
+%type<tokenp>	blocks
+
+%start grammar
+
+%%
+grammar		: sections
+			{
+			    filter( $1 );		/* filter parse tree */
+			    freeTree( $1 );		/* free parse-tree storage (optional: used with purify) */
+			}
+		;
+
+sections	: defsection_opt mark rulesection usersection_opt
+			{
+			    $$ = new Token( "sections", _SECTIONS );
+			    $1->left = $2;
+			    $2->left = $3;
+			    $3->left = $4;
+			    $$->down = $1;
+			}
+		;
+
+mark		: MARK
+		| error					/* missing %% */
+			{
+			    cerr << "no input grammar, missing %% mark" << endl;
+			    exit( -1 );
+			}
+		;
+
+defsection_opt	: /* empty */
+			{
+			    //cerr << "defsection_opt1: " << endl;
+			    $$ = new Token( "declaration_opt", _DEFSECTION_OPT );
+			}
+		| declarations
+			{
+			    //cerr << "defsection_opt2: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = new Token( "declaration_opt", _DEFSECTION_OPT );
+			    $$->down = declstart;
+			}
+		;
+
+declarations	: literalblock
+			{
+			    //cerr << "declarations1: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = declstart = $1;
+			}
+		| declaration
+			{
+			    //cerr << "declarations2: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = declstart = new Token( "declaration", _DECLARATION );
+			    $$->down = $1;
+			}
+		| declarations literalblock
+			{
+			    //cerr << "declarations3: "<< $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->left = $2;
+			    $$ = $2;
+			}
+		| declarations declaration
+			{
+			    //cerr << "declarations4: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $$ = new Token( "declaration", _DECLARATION );
+			    $1->left = $$;
+			    $$->down = $2;
+			}
+		;
+
+literalblock	: LCURL
+			{ lexC(); }
+		  ccode_opt
+			{ $<tokenp>$ = new Token( lexYacc(), CODE ); }
+		  RCURL
+			{
+			    //cerr << "literalblock: " << $1->text << "(" << $1 << ") " << $<tokenp>4->text << " " << $5->text << "(" << $5 << ")" << endl;
+			    $1->left = $<tokenp>4;
+			    $<tokenp>4->left = $5;
+			    $$ = new Token( "literalblock", _LITERALBLOCK );
+			    $$->down = $1;
+			}
+		;
+
+declaration	: union
+		| START IDENTIFIER
+			{
+			    $1->left = $2;
+			    $$ = $1;
+			}
+                | rword tag_opt namenolist
+			{
+			    Token *n = new Token( "namenolist", _NAMENOLIST );
+			    n->down = nameliststart;
+			    $1->left = $2;
+			    $2->left = n;
+			    $$ = $1;
+			}
+		| TYPE tag_opt namelist
+			{
+			    Token *n = new Token( "namelist", _NAMELIST );
+			    n->down = nameliststart;
+			    $1->left = $2;
+			    $2->left = n;
+			    $$ = $1;
+			}
+                | PURE_PARSER
+		| SEMANTIC_PARSER
+                | EXPECT INTEGER			/* bison */
+			{
+			    $1->left = $2;
+			    $$ = $1;
+			}
+                | THONG					/* bison */
+		;
+
+union		: UNION
+		  '{'
+			{ lexC(); }
+		  ccode_opt
+			{
+			    // Remove the trailing '}' which is added in lex.
+			    string temp( lexYacc() );
+			    $<tokenp>$ = new Token( temp.substr( 0, temp.length() - 1 ), CODE );
+			}
+		  '}'
+			{
+			    $1->left = $2;
+			    $2->left = $<tokenp>5;
+			    $<tokenp>5->left = $6;
+			    $$ = $1;
+			}
+		;
+
+rword		: TOKEN
+		| LEFT
+		| RIGHT
+		| NONASSOC
+		;
+
+tag_opt		: /* empty */
+			{
+			    //cerr << "tag_opt" << endl;
+			    $$ = new Token( "tag_opt", _TAG_OPT );
+			}
+		| '<' IDENTIFIER '>'
+			{
+			    $1->left = $2;
+			    $2->left = $3;
+			    $$ = new Token( "tag_opt", _TAG_OPT );
+			    $$->down = $1;
+			}
+		;
+
+namenolist	: nameno
+			{
+			    //cerr << "namenolist1: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = nameliststart = $1;
+			}
+		| namenolist nameno
+			{
+			    //cerr << "namenolist2: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->left = $2;
+			    $$ = $2;
+			}
+		| namenolist ',' nameno
+			{
+			    //cerr << "namenolist3: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ") " << $3->text << "(" << $3 << ")" << endl;
+			    $1->left = $2;
+			    $2->left = $3;
+			    $$ = $3;
+			}
+		;
+
+nameno		: name
+			{
+			    $$ = new Token( "nameno", _NAMENO );
+			    $$->down = $1;
+			}
+		| name INTEGER
+			{
+			    $$ = new Token( "nameno", _NAMENO );
+			    $1->left = $2;
+			    $$->down = $1;
+			}
+		;
+
+namelist	: name
+			{
+			    //cerr << "namelist1: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = nameliststart = $1;
+			}
+		| namelist name
+			{
+			    //cerr << "namelist2: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->left = $2;
+			    $$ = $2;
+			}
+		| namelist ',' name
+			{
+			    //cerr << "namelist3: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ") " << $3->text << "(" << $3 << ")" << endl;
+			    $1->left = $2;
+			    $2->left = $3;
+			    $$ = $3;
+			}
+		;
+
+name		: IDENTIFIER
+		| CHARACTER
+		;
+
+rulesection	: rules
+			{
+			    //cerr << "rulesection1: " << $1->text << "(" << $1 << ")" << endl;
+			    $$ = new Token( "rulesection", _RULESECTION );
+			    $$->down = $1;
+			}
+		| error					/* no rules */
+			{
+			    cerr << "no rules in the input grammar" << endl;
+			    exit( -1 );
+			}
+		;
+
+// These grammar rules are complex because the Yacc language is LR(2) due to the optional ';' at the end of
+// rules. The following rules convert the LR(2) grammar into LR(1) by lengthening the rules to allow
+// sufficient look ahead. Unfortunately, this change makes handling the semantic actions more complex because
+// there are two lists (rules, rhs) being built but only one list tail can be returned through $$ for
+// chaining.
+
+rules		: lhs rhs
+			{
+			    //cerr << "rules1: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $$ = rulestart;
+			}
+		| lhs rhs ';'
+			{
+			    //cerr << "rules2: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ") " << $3->text << "(" << $3 << ")" << endl;
+			    $2->addDownLeftTail( $3 );
+			    $$ = rulestart;
+			}
+		;
+
+lhs		: IDENTIFIER ':'
+			{
+			    //cerr << "lhs: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $$ = new Token( "lhs", _LHS );
+			    //cerr << " lhs: "  << $$->text << "(" << $$ << ")" << endl;
+			    $1->left = $2;
+			    $$->down = $1;
+			}
+		;
+
+rhs		: /* empty */
+			{
+			    //cerr << "rhs1: " << $<tokenp>0->text << "(" << $<tokenp>0 << ")"  << endl;
+			    rulestart = new Token( "rule", _RULE );
+			    rulestart->down = $<tokenp>0; // initial lhs is already on the stack from "rules"
+			    $$ = new Token( "rhs", _RHS );
+			    //cerr << "  rhs: " << $$->text << "(" << $$ << ")" << endl;
+			    $<tokenp>0->left = $$;
+			}
+		| rhs lhs
+			{
+			    //cerr << "rhs2: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    Token *temp = new Token( "rule", _RULE );
+			    rulestart->addLeftTail( temp );
+			    temp->down = $2;
+			    $$ = new Token( "rhs", _RHS );
+			    //cerr << "  rhs: "  << $$->text << "(" << $$ << ")" << endl;
+			    $2->left = $$;
+			}
+		| rhs ';' lhs
+			{
+			    //cerr << "rhs3: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ") " << $3->text << "(" << $3 << ")" << endl;
+			    $1->addDownLeftTail( $2 );
+			    Token *temp = new Token( "rule", _RULE );
+			    rulestart->addLeftTail( temp );
+			    temp->down = $3;
+			    $$ = new Token( "rhs", _RHS );
+			    //cerr << "  rhs: "  << $$->text << "(" << $$ << ")" << endl;
+			    $3->left = $$;
+			}
+		| rhs prod
+			{
+			    //cerr << "rhs4: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->addDownLeftTail( $2 );
+			    $$ = $1;
+			}
+		| rhs '|'
+			{
+			    //cerr << "rhs5: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->addDownLeftTail( $2 );
+			    $$ = new Token( "rhs", _RHS );
+			    $1->left = $$;
+			    //cerr << "  rhs: "  << $$->text << "(" << $$ << ")" << endl;
+			}
+		;
+
+prod		: action
+		| IDENTIFIER
+		| CHARACTER
+		| prec
+		;
+
+prec		: PREC name
+			{
+			    //cerr << "prec: " << $1->text << "(" << $1 << ") " << $2->text << "(" << $2 << ")" << endl;
+			    $1->left = $2;
+			    $$ = new Token( "prec", _PREC );
+			    $$->down = $1;
+			}
+		;
+
+action		: '{'
+			{ lexC(); }
+		  ccode_opt
+			{
+			    // Remove the trailing '}' added in lex.
+			    string temp( lexYacc() );
+			    $<tokenp>$ = new Token( temp.substr( 0, temp.length() - 1 ), CODE );
+			}
+		  '}'
+			{
+			    $1->left = $<tokenp>4;
+			    $<tokenp>4->left = $5;
+			    $$ = new Token( "action", _ACTION );
+			    $$->down = $1;
+			}
+		;
+
+usersection_opt	: /* empty */
+			{
+			    //cerr << "usersection_opt" << endl;
+			    // attach remaining WS to fictitious code
+			    Token *temp = new Token( "", ws_list, CODE );
+			    $$ = new Token( "usersection_opt", _USERSECTION_OPT );
+			    $$->down = temp;
+			}
+		| MARK
+			{ lexC(); }
+		  ccode_opt
+			{
+			    Token *temp = new Token( lexYacc(), CODE );
+			    //cerr << "usersection_opt: " << $1->text << " " << temp->text << endl;
+			    $1->left = temp;
+			    $$ = new Token( "usersection_opt", _USERSECTION_OPT );
+			    $$->down = $1;
+			}
+		;
+
+ccode_opt	: /* empty */			{}
+		| blocks
+		;
+
+// This rule matches internal braces "{}" in C code to the level of the braces of a union/action.  These
+// internal braces are returned as Tokens from the lexer but are unused because the braces are already
+// concatenated into the code string built by the lexer. Therefore, the tokens for the braces are immediately
+// deleted.
+
+blocks		: '{' { delete $1; } ccode_opt '}' { delete $4; }
+		| blocks '{' { delete $2; } ccode_opt '}' { delete $5; }
+		;
+%%
+
+/* Local Variables: */
+/* fill-column: 110 */
+/* compile-command: "gmake" */
+/* End: */
