
###############################################################################
#                                                                             #
#  Lout @EiffelPrint package for formatting Eiffel programs (Version 1.3)     #
#                                                                             #
#  Version 1.0 by Jeffrey H. Kingston, April 1995 (adapted from @CPrint).     #
#  Version 1.1 by Jeffrey H. Kingston, July 1995.                             #
#  Version 1.3 by Jeffrey H. Kingston, November 1996.                         #
#                                                                             #
#  This package uses a filtered body parameter to convert Eiffel source code  #
#  into Lout source.  The filter program is eif2lout.  The rules are from     #
#                                                                             #
#     Bertrand Meyer, "Eiffel: The Language", Prentice-Hall 1992.             #
#                                                                             #
#  especially Appendices A and G.  The default is to follow these rules,      #
#  but others are possible if you want them.                                  #
#                                                                             #
###############################################################################

export @Eiffel
def @EiffelPrint
    named style              { varying @OrIfPlain fixed }  # print style
    named pipe               {           }  # pipe through this first

    named fixedfont          { Courier   }  # font family if fixed
    named fixedstrings       { Base      }  # string face if fixed
    named fixedidentifiers   { Base      }  # identifier face if fixed
    named fixedcomments      { Base      }  # comment face if fixed
    named fixedkeywords      { Base      }  # keyword face if fixed
    named fixednumbers       { Base      }  # number face if fixed
    named fixedoperators     { Base      }  # operator face if fixed
    named fixedsize          { -1.0p     }  # font size if fixed
    named fixedline          { 1.0vx     }  # line-space if fixed
    named fixedtabin	     { 8	 }  # tab interval if fixed
    named fixedtabout	     { 8s	 }  # tab width if fixed

    named varyingfont        {           }  # font family if varying
    named varyingstrings     { Slope     }  # string face if varying
    named varyingidentifiers { Slope     }  # identifier face if varying
    named varyingcomments    { Base      }  # comment face if varying
    named varyingkeywords    { Bold      }  # keyword face if varying
    named varyingnumbers     { Base      }  # number face if varying
    named varyingoperators   { Base      }  # operator face if varying
    named varyingsize        { 1.0f      }  # font size if varying
    named varyingline        { 1.0vx     }  # line-space if varying
    named varyingtabin       { 8	 }  # tab interval if varying
    named varyingtabout      { 3f	 }  # tab width if varying

    named symbolfont         {           }  # font family if symbol
    named symbolstrings      { Slope     }  # string face if symbol
    named symbolidentifiers  { Slope     }  # identifier face if symbol
    named symbolcomments     { Base      }  # comment face if symbol
    named symbolkeywords     { Bold      }  # keyword face if symbol
    named symbolnumbers      { Base      }  # number face if symbol
    named symboloperators    { Base      }  # operator face if symbol
    named symbolsize         { 1.0f      }  # font size if symbol
    named symbolline         { 1.0vx     }  # line-space if symbol
    named symboltabin        { 8	 }  # tab interval if symbol
    named symboltabout       { 3f	 }  # tab width if symbol

@Begin

    export
    
	"$>" "`" @L @S @C

	"0"   "1"   "2"   "3"   "4"   "5"   "6"   "7"   "8"   "9"
	"0."  "1."  "2."  "3."  "4."  "5."  "6."  "7."  "8."  "9."
	"0.." "1.." "2.." "3.." "4.." "5.." "6.." "7.." "8.." "9.."

	";" "," ":" "." "!" "!!" "=" "/=" "->" ".." "..." "(" ")"
	"[" "]" "${" "$}" "<<" ">>" ":=" "?=" "'" "+" "-" "$"
	"^" "*" "$/" "$//" "$$/" "<" ">" "<=" ">="

	alias	    all		and	    as		BIT	    BOOLEAN
	CHARACTER   check	class	    creation	Current	    debug
	deferred    do		DOUBLE	    else	elseif	    end
	ensure	    expanded	export	    external	false	    feature
	from	    frozen	if	    implies	indexing    infix
	inherit	    inspect	INTEGER	    invariant	is	    like
	local	    loop	NONE	    obsolete	old	    once
	or	    prefix	REAL	    redefine	rename	    require
	rescue	    Result	retry	    select	separate    STRING
	strip	    then	true	    undefine	unique	    until
	variant	    when	xor

	not	    interface

    def @Eiffel
	named style        { style         }  # style
	named pipe         { pipe          }  # font family
	named font         { dft           }  # font family
	named strings      { dft           }  # string font
	named identifiers  { dft           }  # ident. font
	named comments     { dft           }  # comment font
	named keywords     { dft           }  # keyword font
	named numbers      { dft           }  # number font
	named operators    { dft           }  # operator font
	named size         { dft           }  # font size
	named line         { dft           }  # line-space
	named tabin        { dft           }  # tab interval
	named tabout       { dft           }  # tab width
	body @Body			      # filtered, see below
    @Begin

	def @Test	# returns x unless x is dft
	    left x
	    named iffixed {}
	    named ifvarying {}
	    named ifsymbol {}
	{
	    x @Case {
		dft @Yield {
		    style @Case {
			fixed   @Yield { iffixed   }
			varying @Yield { ifvarying }
			symbol  @Yield { ifsymbol  }
		    }
		}
		else @Yield x
	    }
	}

	def @InitTab
	{
	  tabin @Test
	      iffixed   { fixedtabin   }
	      ifvarying { varyingtabin }
	      ifsymbol  { symboltabin  }
	}

	def @InitTabWidth
	{
	  tabout @Test
	      iffixed   { fixedtabout   }
	      ifvarying { varyingtabout }
	      ifsymbol  { symboltabout  }
	}

	def @Filter
	{
	    pipe @Case {
		"" @Yield {
	    	    eif2lout -r -i{@FilterIn} -o{@FilterOut} -e{@FilterErr}
			-t{@InitTab} -T{@InitTabWidth}
		}
		else @Yield {
	    	    "cat" @FilterIn "|" pipe "|" eif2lout -r -o{@FilterOut}
			-e{@FilterErr} -t{@InitTab} -T{@InitTabWidth}
		}
	    }
	}

	def @InitFontFamily
	{
	  font @Test
	      iffixed   { fixedfont   }
	      ifvarying { varyingfont }
	      ifsymbol  { symbolfont  }
	}

	def @InitSize
	{
	  size @Test
	      iffixed   { fixedsize   }
	      ifvarying { varyingsize }
	      ifsymbol  { symbolsize  }
	}

	def @InitLine
	{
	  line @Test
	      iffixed   { fixedline   }
	      ifvarying { varyingline }
	      ifsymbol  { symbolline  }
	}

	def @S		# for formatting Eiffel strings
	    right x
	{
	    # "\"" &
	    strings @Test
	      iffixed   { fixedstrings   }
	      ifvarying { varyingstrings }
	      ifsymbol  { symbolstrings  }
	    @Font x
	    # & "\""
	}

	def "`"
	{
	    style @Case {
		symbol	@Yield { "`" }
		else	@Yield { "'" }
	    }
	}

	def @L		# for formatting Eiffel character literals
	    right x
	{
	    ` &
	    strings @Test
	      iffixed   { fixedstrings   }
	      ifvarying { varyingstrings }
	      ifsymbol  { symbolstrings  }
	    @Font x
	    & '
	}

	def @Ident	# for formatting Eiffel identifiers
	    right x
	{
	    identifiers @Test
	      iffixed   { fixedidentifiers   }
	      ifvarying { varyingidentifiers }
	      ifsymbol  { symbolidentifiers  }
	    @Font x
	}

	def @C		# for formatting Eiffel comments
	    right x
	{
	    comments @Test
	      iffixed   { fixedcomments   }
	      ifvarying { varyingcomments }
	      ifsymbol  { symbolcomments  }
	    @Font x
	}

	def @K		# for formatting Eiffel keywords
	    right x
	{
	    keywords @Test
	      iffixed   { fixedkeywords   }
	      ifvarying { varyingkeywords }
	      ifsymbol  { symbolkeywords  }
	    @Font x
	}

	def @N		# for formatting Eiffel numbers
	    right x
	{
	    numbers @Test
	      iffixed   { fixednumbers   }
	      ifvarying { varyingnumbers }
	      ifsymbol  { symbolnumbers  }
	    @Font x
	}

	def @O		# for formatting Eiffel operators
	    right x
	{
	    operators @Test
	      iffixed   { fixedoperators   }
	      ifvarying { varyingoperators }
	      ifsymbol  { symboloperators  }
	    @Font x
	}

	def @A		# get characters from the Adobe Symbol font
	    left sym
	    right x
	{
	    style @Case {
		symbol	@Yield { { Symbol Base } @Font @Char sym }
		else	@Yield { x			}
	    }
	}

	macro "$>" { {} & }

	def "0"		{ @N "0"			}
	def "1"		{ @N "1"			}
	def "2"		{ @N "2"			}
	def "3"		{ @N "3"			}
	def "4"		{ @N "4"			}
	def "5"		{ @N "5"			}
	def "6"		{ @N "6"			}
	def "7"		{ @N "7"			}
	def "8"		{ @N "8"			}
	def "9"		{ @N "9"			}

	def "0."	{ @N "0."			}
	def "1."	{ @N "1."			}
	def "2."	{ @N "2."			}
	def "3."	{ @N "3."			}
	def "4."	{ @N "4."			}
	def "5."	{ @N "5."			}
	def "6."	{ @N "6."			}
	def "7."	{ @N "7."			}
	def "8."	{ @N "8."			}
	def "9."	{ @N "9."			}

	def "0.."	{ {@N "0"}".."			}
	def "1.."	{ {@N "1"}".."			}
	def "2.."	{ {@N "2"}".."			}
	def "3.."	{ {@N "3"}".."			}
	def "4.."	{ {@N "4"}".."			}
	def "5.."	{ {@N "5"}".."			}
	def "6.."	{ {@N "6"}".."			}
	def "7.."	{ {@N "7"}".."			}
	def "8.."	{ {@N "8"}".."			}
	def "9.."	{ {@N "9"}".."			}

	def ";"		{		  @O ";"	}
	def ","		{		  @O ","	}
	def ":"		{		  @O ":"	}
	def "."		{    "1.2f" @Font "+0.05f" @VShift @O "." &"0.05f"}
	def "!"		{ 		  @O "!" &"0.05f" }
	def "!!"	{ 		  @O "!!" &"0.05f" }
	def "="		{ equal @A	  @O "="	}
	def "/="	{ notequal @A	  @O "/="	}
	def "->"	{ arrowright @A	  @O "->"	}
	def ".."	{		     ".."       } 
	def "..."	{		     "..."      } 
	def "("		{		  @O "("	}
	def ")"		{		  @O ")"	}
	def "["		{		  @O "["	}
	def "]"		{		  @O "]"	}
	def "${"	{		  @O "{"	}
	def "$}"	{		  @O "}"	}
	def "<<"	{		     { < }{ < }	}
	def ">>"	{		     { > }{ > }	}
	def ":="	{		  @O ":="	}
	def "?="	{		  @O "?="	}
	def "'"		{		  @O "'"	}
	def "+"		{ plus  @A	  @O "+"	}

	def "-"
	{
	    style @Case {
		fixed	@Yield "-"
		varying @Yield { { Symbol Base } @Font @Char minus }
		symbol  @Yield { { Symbol Base } @Font @Char minus }
	    }
	}

	def "$"		{		  @O "$"	}
	def "^"		{		  @O "^"	}
	def "*"		{ asteriskmath @A @O "0.5w" @VShift "*" }
	def "$/"	{		  @O "/"	}
	def "$//"	{		  @O "//"	}
	def "$$/"	{		  @O "\\\\"	}
	def "<"		{ less @A	  @O "<"	}
	def ">"		{ greater @A	  @O ">"	}
	def "<="	{ lessequal @A	  @O "<="	}
	def ">="	{ greaterequal @A @O ">="	}

	def alias	{ @K "alias"		}
	def all		{ @K "all"		}
	def and		{ @K "and"		}
	def as		{ @K "as"		}
	def BIT		{ @Ident "BIT"		}
	def BOOLEAN	{ @Ident "BOOLEAN"	}

	def CHARACTER	{ @Ident "CHARACTER"	}
	def check	{ @K "check"		}
	def class	{ @K "class"		}
	def creation	{ @K "creation"		}
	def Current	{ @Ident "Current"	}
	def debug	{ @K "debug"		}

	def deferred	{ @K "deferred"		}
	def do		{ @K "do"		}
	def DOUBLE	{ @Ident "DOUBLE"	}
	def else	{ @K "else"		}
	def elseif	{ @K "elseif"		}
	def end		{ @K "end"		}

	def ensure	{ @K "ensure"		}
	def expanded	{ @K "expanded"		}
	def export	{ @K "export"		}
	def external	{ @K "external"		}
	def false	{ @K "false"		}
	def feature	{ @K "feature"		}

	def from	{ @K "from"		}
	def frozen	{ @K "frozen"		}
	def if		{ @K "if"		}
	def implies	{ @K "implies"		}
	def indexing	{ @K "indexing"		}
	def infix	{ @K "infix"		}

	def inherit	{ @K "inherit"		}
	def inspect	{ @K "inspect"		}
	def INTEGER	{ @Ident "INTEGER"	}
	def invariant	{ @K "invariant"	}
	def is		{ @K "is"		}
	def like	{ @K "like"		}

	def local	{ @K "local"		}
	def loop	{ @K "loop"		}
	def NONE	{ @Ident "NONE"		}
	def obsolete	{ @K "obsolete"		}
	def old		{ @K "old"		}
	def once	{ @K "once"		}

	def or		{ @K "or"		}
	def prefix	{ @K "prefix"		}
	def REAL	{ @Ident "REAL"		}
	def redefine	{ @K "redefine"		}
	def rename	{ @K "rename"		}
	def require	{ @K "require"		}

	def rescue	{ @K "rescue"		}
	def Result	{ @Ident "Result"	}
	def retry	{ @K "retry"		}
	def select	{ @K "select"		}
	def separate	{ @K "separate"		}
	def STRING	{ @Ident "STRING"	}

	def strip	{ @K "strip"		}
	def then	{ @K "then"		}
	def true	{ @K "true"		}
	def undefine	{ @K "undefine"		}
	def unique	{ @K "unique"		}
	def until	{ @K "until"		}

	def variant	{ @K "variant"		}
	def when	{ @K "when"		}
	def xor		{ @K "xor"		}

	def not		{ @K "not"		}
	def interface	{ @K "interface"	}

	{ @InitFontFamily Base @InitSize } @Font @Ident
	{ @InitLine lines } @Break @Body

    @End @Eiffel

@End @EiffelPrint
