## core-prettyprinter-types-g.pkg
#
# Define the core datastructures used by
#
#
src/lib/prettyprint/big/src/core-prettyprinter-g.pkg#
# and related packages. We need to externalize these so
# that we can reduce clutter in core-prettyprinter-g.pkg by
# moving debug stuff etc to support packages.
# Compiled by:
#
src/lib/prettyprint/big/prettyprinter.libstipulate
herein
# This generic is invoked (only) from
#
#
src/lib/prettyprint/big/src/core-prettyprinter-g.pkg #
generic package core_prettyprinter_types_g (
# ==========================
#
package out: Prettyprint_Output_Stream; # Prettyprint_Output_Stream is from
src/lib/prettyprint/big/src/out/prettyprint-output-stream.api )
: (weak) Core_Prettyprinter_Types # Core_Prettyprinter_Types is from
src/lib/prettyprint/big/src/core-prettyprinter-types.api {
package out = out;
Left_Margin_Is # How should we compute the left margin for a box?
= BOX_RELATIVE { blanks: Int, tab_to: Int, tabstops_are_every: Int } # Indent left margin relative to left margin of containing box.
| CURSOR_RELATIVE { blanks: Int, tab_to: Int, tabstops_are_every: Int }
# Set left margin by tabbing from cursor, where tabstops are every 'Int' chars.
;
Phase1_Token
#
= NEWLINE
| BOX Box
| TAB { blanks: Int,
tab_to: Int,
tabstops_are_every: Int
}
| INDENT Int
# Change left margin for duration of box. Int == i: if (i != 0) box.left_margin += i;
# else box.left_margin = original_left_margin_for_box;
# fi;
| BREAK Break
| BLANKS Int
# "LIT" == "LITERAL (text)" -- text printed exactly as presented, without interpretation.
| LIT String
# Raw text. This includes traitful_text. The width and texttraits information is taken care of when they are inserted into output stream.
| ENDLIT String
# A special hack so that (e.g.) semicolons can appear at the end of a preceding box instead of getting a line of their own, which usually we don't want.
| PUSH_TT out::Texttraits
| POP_TT
| CONTROL (out::Prettyprint_Output_Stream -> Void)
# Device control operation. This provides an escape for ejecting a page or selecting a pen or any other unanticipated stuff.
withtype
Break = { wrap: Ref Bool, # This controls whether we take the 'ifwrap' or 'ifnotwrap' action.
#
ifnotwrap: { blanks: Int, # Start by printing this many blanks.
tabstops_are_every: Int, # 0 == nop, n > 0 means tabs are set every n columns.
tab_to: Int # Print blanks until (column % tabstops_are_every) == tab_to. This may result in zero blanks printing.
},
ifwrap: { blanks: Int, # Start by printing this many blanks.
tabstops_are_every: Int, # 0 == nop, n > 0 means tabs are set every n columns.
tab_to: Int # Print blanks until (column % tabstops_are_every) == tab_to. This may result in zero blanks printing.
}
}
also
Wrap_Policy = { name: String,
#
code: { target_width: Int,
box_contents: List Phase1_Token
}
->
{ actual_box_width: Int,
is_multiline: Bool
}
}
also
Box = { left_margin_is: Left_Margin_Is, # The left margin for the box is computed by adding an int to either the cursor or the previous left margin.
target_width: Int, # We try to fit box contents into this width. We can break only where allowed (possibly nowhere), so we cannot guarantee success.
actual_width: Ref Int, # Length of contents if newline free, else length of first line.
#
id: Int, # Unique id number per box. Only used for debugging/display.
rulename: Ref(String), # Name of rule generating box, set via pp.rulename "T1" defaulting to "". Used only for debugging/display.
#
is_multiline: Ref Bool, # TRUE iff there's a NEWLINE somewhere inside.
contents: Ref List Phase1_Token, # This is empty until box is closed, after that it == reverse (*reversed_contents).
reversed_contents: Ref List Phase1_Token, # We accumulate tokens in this while constructing box, by successively prepending them.
#
wrap_policy: Wrap_Policy
};
Prettyprinter_Configuration_Args # Futureproofing -- args which code clients can pass to us to customize the prettyprinter.
# # We can add more cases here in future as needed, without breaking backward compatibility.
= DEFAULT_TARGET_BOX_WIDTH Int
| DEFAULT_LEFT_MARGIN_IS Left_Margin_Is
| DEFAULT_WRAP_POLICY Wrap_Policy
| TABSTOPS_ARE_EVERY Int
# Usually 4.
;
Prettyprinter
=
{
output_stream: out::Prettyprint_Output_Stream, # Where to send formatted output.
output_stream_is_closed: Ref( Bool ), # TRUE iff the stream is closed.
box: Ref Box,
nested_boxes: Ref (List(Box)),
box_nesting: Ref Int, # Current depth of 'nested_boxes'. Used only to catch infinite loops.
next_box_id: Ref Int,
texttraits_stack: Ref( List(out::Texttraits) )
};
package b {
#
Phase2_Token # Same as Phase1_Token except without BOX, TAB or BREAK.
#
= NEWLINE
| BLANKS Int
| LIT String
| ENDLIT String
| PUSH_TT out::Texttraits
| POP_TT
| CONTROL (out::Prettyprint_Output_Stream -> Void)
;
};
package c {
#
Phase3_Token # Same as Phase2_Token except without ENDLIT.
#
= NEWLINE
| BLANKS Int
| LIT String
| PUSH_TT out::Texttraits
| POP_TT
| CONTROL (out::Prettyprint_Output_Stream -> Void)
;
};
package d {
#
Phase4_Token # Same as Phase3_Token except without NEWLINE.
#
= BLANKS Int
| LIT String
| PUSH_TT out::Texttraits
| POP_TT
| CONTROL (out::Prettyprint_Output_Stream -> Void)
;
};
};
end;
## COPYRIGHT (c) 2005 John Reppy (http://www.cs.uchicago.edu/~jhr)
## All rights reserved.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.