SMLFormat: Pretty Printer for Standard ML

@author YAMATODANI Kiyoshi
@version $Id: OVERVIEW_ja.txt,v 1.9 2008/08/10 13:44:01 kiyoshiy Exp $

========================================
1. SMLFormat

SMLFormat͎̓\B

  * smlformat
  * formatlib


====================
1.1. smlformat

smlformat͒PƂŎgpc[łB
smlformatւ̓͂type/datatype錾܂SML\[Xt@C(*.ppg)łB
type/datatype錾ɂ́Ǎ^̒l𕶎񉻂ďo͂ۂ̏AȃRg`Ŏw肷B̃RgtH[}bgRg(format comment)ƌĂԁB
smlformat́Atype/datatype錾ƃtH[}bgRgƂ͂AtH[}b^(formatter)ƌĂԊ֐SMLR[h𐶐B
^tɑ΂ĐtH[}b^́A^t̒l󂯎A̒l𐮌`o͂邽߂̒ԕ\Ԃ֐łB̒ԕ\tH[}bg(format expression)ƌĂԁB

  -------(Absyn.ppg)-----------------------------------------------
  structure Absyn =
  struct

    (*%
     *)
    datatype exp
      = (*%
         * @format(const * loc) {const}
         *)
        EXPCONSTANT of constant * loc
      | (*%
         * @format(cond * ifTrue * ifFalse * loc)
         *            N0{ "if" 2[ +d {cond} ]
         *             +1 "then" 2[ +d {ifTrue} ]
         *             +1 "else" 2[ +d {ifFalse} ] }
         *)
        EXPIF of exp * exp * exp * loc
      | (*%
         * @format(exp * rule rules * loc)
         * N0{ "case" 2[+d {exp}] 2[+1 "of" ]+ {rules(rule)(~2[ +1 "|"] +)} }
         * @format:rule(pat * exp) {{pat} + "=>" +1 {exp}}
         *)
        EXPCASE of exp * (pat * exp) list * loc

        :

  end
  -----------------------------------------------------------------

Absyn.ppg͂Ƃė^ƁAsmlformat͂̂悤ɓ̓t@C̓eɃtH[}b^̒`}SMLt@C𐶐B

  -------(Absyn.ppg.sml)-------------------------------------------
  structure Absyn =
  struct

    (*%
     *)
    datatype exp
      = 
        :

    fun format_exp x = ...

  end
  -----------------------------------------------------------------

format_exp͂̌^B

  val format_exp : exp -> FormatExpression.expression list

smlformatR}h͎̃R}hIvV󂯎B

  --stdout
    .ppg.smlt@CɑւWo͂Ɍʂ̃R[hoB

  --with-line-directive
    R[ḧʒuSMLRpCɎwsԍfBNeBu
    ʂ̃R[hɑ}B

====================
1.2. formatlib

formatlib́ASMLFormatXgN`񋟂B
SMLFormatXgN`́AprettyPrint֐B
prettyPrint֐́AtH[}bgƏo͌ƂĎ󂯎AtH[}bg̃eLXg\AɂȂׂ܂悤ɐ`ďo͂B
prettyPrint֐͂̌^B

  val prettyPrint :
        PrinterParameter.printerParameter ->
          FormatExpression.expression list ->
            string

smlformattH[}b^SMLFormat.prettyPrintpāA̂悤Absyn.exp^̎expression̒l𐮌`o͂邱ƂłB

  print
    (SMLFormat.prettyPrint
     {newlineString = "\n", spaceString = " ", columns = 60}
     (Absyn.format_exp expression))

ł͌Ƃ60w肵ĂB
Ƃ΂̂悤ɏo͂B

    123456789012345678901234567890123456789012345678901234567890
    ------------------------------------------------------------
    let
      val exn = getException context
      val message =
          case exn
            of SystemError => "SystemError"
             | UserError msg =>
               "User:" ^ msg ^
               (
                concatWith "\n"
                (
                 map (frameToString context) (getFrames context)
                )
               )
    in raise Error message end

tH[}bgRgł̏wύX邱ƂɂAƂΎ̂悤ɏo͌`𒲐邱ƂłB

    123456789012345678901234567890123456789012345678901234567890
    ------------------------------------------------------------
    let val exn = getException context
        val message = case exn of
                          SystemError => "SystemError"
                        | UserError msg =>
                          "User:" ^ msg ^
                            (
                             concatWith "\n"
                               (
                                map (frameToString context)
                                  (getFrames context)
                               )
                            )
    in raise Error message end


========================================
2. tH[}bg


====================
2.1. L@

colƃtH[}bg̗ exp1 ... expn ͂ƂāA
 text ɕϊ邱Ƃ

  exp1 ... expn
  col=>
  text

ƕ\LB
͏ȗꍇB

  exp1 ... expn
  =>
  text


====================
2.2. 萔

dpň͂܂ꂽ萔͂̂܂܏o͂B

  "jugemu"
  =>
  jugemu

A镶萔͘Aďo͂B

  "jugemu" "jugemu"
  =>
  jugemujugemu

Ԃɋ󔒂݂ꍇ́A萔" "gpB

  "jugemu" " " "jugemu" " " "gokounosurikire"
  =>
  jugemu jugemu gokounosurikire

̗ŕ悤ɁA" "͎Ԃ̋󔒂ƎʂɂB


====================
2.3. 󔒎wq

" "̂ɋ󔒎wq(space indicator)'+'gp邱ƂłB

  "jugemu" + "jugemu" + "gokounosurikire"
  =>
  jugemu jugemu gokounosurikire


====================
2.4. swq

񒷂̍vw茅𒴂ꍇo͉͂sȂB

  "jugemu" + "jugemu" + "gokounosurikire" + "kaijarisuigyono"
  40=>
  jugemu jugemu gokounosurikire kaijarisuigyono
  ----------------------------------------
  1234567890123456789012345678901234567890

swq(newline indicator)ɂAsׂʒuw肷邱ƂłB
swqɂ́A1ȏ̐lŗD揇ʂw肷B̏قDxB

s̕KvȂꍇAswq͏o͓eɉeȂB

  "jugemu" 2 "jugemu" 1 "gokounosurikire" 2 "kaijarisuigyono"
  50=>
  jugemujugemugokounosurikirekaijarisuigyono
  --------------------------------------------------
  12345678901234567890123456789012345678901234567890

o͓eɎ܂ȂꍇADx̍swq珇ɉsB

  "jugemu" 2 "jugemu" 1 "gokounosurikire" 2 "kaijarisuigyono"
  40=>
  jugemujugemu
  gokounosurikirekaijarisuigyono
  ----------------------------------------
  1234567890123456789012345678901234567890

Dx2Dx1D悳̂ŁA܂AԖڂ̉swqŉsB

Dxswq́Â̂ꂩ̈ʒuŉsKvꍇÂׂĂ̈ʒuŉsB

  "jugemu" 2 "jugemu" 1 "gokounosurikire" 2 "kaijarisuigyono"
  20=>
  jugemu
  jugemu
  gokounosurikire
  kaijarisuigyono
  --------------------
  12345678901234567890

̗ł́ADx1swqЂƂƁADx2̉swq܂܂ĂB20łꍇA܂Dx1̉swqŉsKvBɁADx2̉swq̂Aŏ̎wqł͉sKvȂAЂƂ̉swqł͉s̕KvB̂߁Ảswq̈ʒuŉsB

ɂ́ADxnƂswqN̈ʒuŉsׂǂ̂悤Ɍ肷B

  1) nƓ邢nႢDx̉swqŉsꍇ͉sB

  2) Dxn荂swq̂N̑OьŒ߂̓̎wqFBƂB̓̐lkWrAW < L ƂȂꍇ͉sB

    L = FBƂɋ܂ꂽtH[}bg̗sɏo͂邽߂ɕKvȌ

    W = F̈ʒuŉsƉ肵ꍇF̒̃JʒuAw茅܂ł̌

         F         N                        B
     ... 1  "abc" +3 "def" 4 "ghi" +3 "jkl" 2 ...
          <-------------------------------->

    FBɂ͂܂ꂽtH[}bgsȂŏo͂ɂ 14(= 3 + 1 + 3 + 0 + 3 + 1 + 3)KvłB܂AFŉsƁA͈̒Jڂo͂JnB܂AF̒ł̃Jʒuw茅܂ł̌́Aw茅ɓBāAw茅14菭ȂꍇɂNł̉sKvɂȂBŐ悤ɁAF̒̃Jʒu͕KJłƂ͌ȂB

  3) ȏ̂ɂYȂꍇAsȂB

ӁF萔"\n"gpΏɂ̈ʒuŉs邪A݂SMLFormat͕萔ɉs̑^uȂǂ̏܂߂邱ƂF߂ĂȂB


==========
2.4.1. 󔒎wqƉswq

󔒎wqƉswq͑gݍ킹Ďgp邱ƂłB̏ꍇAs̕KvȂȂ΋󔒈ꕶo͂B

  "jugemu" +2 "jugemu" +1 "gokounosurikire" +2 "kaijarisuigyono"
  50=>
  jugemu jugemu gokounosurikire kaijarisuigyono
  --------------------------------------------------
  12345678901234567890123456789012345678901234567890

s̕Kvꍇ́A󔒂o͂ɂ̈ʒuŉsB

  "jugemu" +2 "jugemu" +1 "gokounosurikire" +2 "kaijarisuigyono"
  40=>
  jugemu jugemu
  gokounosurikire kaijarisuigyono
  ----------------------------------------
  1234567890123456789012345678901234567890

ӁFĽʂLɂɂ́A󔒕Ɖs𑱂Ďw肵Ȃ΂ȂȂB󔒎wqƉswq̊Ԃɋ󔒂ނƂꂼʂɉ߂A󔒎wq͂˂ɋ󔒕o͂B

ӁF萔" "gpꍇɂ͉s̗Lɂ炸ɋ󔒈ꕶo͂B

  "jugemu" +2 "jugemu" " "1 "gokounosurikire" +2 "kaijarisuigyono"
  40=>
  jugemu jugemu 
  gokounosurikire kaijarisuigyono
  ----------------------------------------
  1234567890123456789012345678901234567890

ɂAo͌ʂ̈sڂ̍sɂ͋󔒈ꕶo͂ĂB

==========
2.4.2. swq

܂ł̉swqɂ́AׂėDxw肵B
Dxw肵Ȃswqgp邱ƂłB
swq(deferred newline indicator)ƌĂԁB
܂ł̗Dxw肷swqDswq(preferred newline indicator)ƌĂԁB
swq'd'ƕ\LB
ׂĂ̗Dswq̈ʒuŉsĂw茅𒴉߂ꍇɌAswqw肳ꂽʒuŉsB

  "jugemu" +d "jugemu" +1 "gokounosurikire" +2 "kaijarisuigyono"
  30=>
  jugemu jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̗ł́ADswqł͉sĂ邪Aswqł͉sȂB
ɏȌw肷Ɨswq̈ʒułsB

  "jugemu" +d "jugemu" +1 "gokounosurikire" +2 "kaijarisuigyono"
  10=>
  jugemu
  jugemu
  gokounosurikire
  kaijarisuigyono
  ----------
  1234567890


==========
2.4.3. swqԂ̊֌W

Oɏqׂ悤ɁAswqŉs̕KvꍇAƓA荂Dx̉swqׂ̂ĂŉsBāA̗ł́ADx2̉swqŉsKvȂɂ炸AŌ̗swqŉs̕Kv邽߁AׂẲswqŉsB

  "jugemu" +2 "jugemu" +1 "gokounosurikire" +d "kaijarisuigyono"
  30=>
  jugemu
  jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

Aswq̊Ԃł́ADx̗D͒`ȂBāA̗ł́AOԖڂ̗swqł͉s邪Aŏ̗swqł͕KvȂ߉sȂB

  "jugemu" +d "jugemu" +1 "gokounosurikire" +d "kaijarisuigyono"
  30=>
  jugemu jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890


==========
2.5. CfgX^bN

swqŉsۂ̍sCfgACfgƒ'['Ŏw肷邱ƂłB']'ɂACfgw̓LZB

  "jugemu" +2 "jugemu" 5[ +1 "gokounosurikire" ] +2 "kaijarisuigyono"
  40=>
  jugemu jugemu
       gokounosurikire kaijarisuigyono
  ----------------------------------------
  1234567890123456789012345678901234567890

2Ԗڂ̉swq̒OŃCfg5w肳Ă邽߁Ao͌ʂ̓sڂ̍s5CfgĂB
3Ԗڂ̉swqł́AOɃCfg̎w肪邽߁Asۂ̃Cfg̓ftHg0ƂȂB

  "jugemu" +2 "jugemu" 5[ +1 "gokounosurikire" ] +2 "kaijarisuigyono"
  30=>
  jugemu
  jugemu
       gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

Cfgw3Ԗڂ̉swq̌Ŏ悤ύXƁAo͌ʂ͂̂悤ɂȂB

  "jugemu" +2 "jugemu" 5[ +1 "gokounosurikire" +2 "kaijarisuigyono"]
  30=>
  jugemu
  jugemu
       gokounosurikire
       kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

Cfg̓X^bNɊǗB
'['́ACfgX^bN̐擪ɃCfgvbV邱ƂwA']'́ACfgX^bN̐擪vf|bv邱ƂwB
swqŉsۂ̃CfǵA̎_ŃCfgX^bNɐς܂ĂCfg̍vlɂ茈肳B

  "jugemu" +2 "jugemu" 5[ +1 "gokounosurikire" 3[ +2 "kaijarisuigyono"]];
  30=>
  jugemu
  jugemu
       gokounosurikire
          kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̗ł́AOԖڂ̉swq̈ʒuŉsꍇ̃Cfg3 + 5 = 8ƂȂB

  "jugemu" 3[ +1 "jugemu" 5[ +2 "gokounosurikire" 3[ +3 "kaijarisuigyono"]]]
  30=>
  jugemu
     jugemu
          gokounosurikire
             kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̎3Ԗڂ̉swqŉsۂ̃CfǵA3 + 5 + 3 = 11ƂȂB

Cfgɂ͕w肷邱ƂłB

  "jugemu" +2 "jugemu" 5[ +1 "gokounosurikire" ~3[ +2 "kaijarisuigyono"]];
  30=>
  jugemu
  jugemu
       gokounosurikire
    kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̗ł́AOԖڂ̉swqł̃Cfg5 + (-3) = 2ƂȂB

ӁFCfg̍v0菬ȂꍇAG[ƂȂB
Ƃ΁A̃tH[}bgł͎OԖڂ̉swqŉsꍇɃCfg 3 + (-5) = -2 ƂȂ邽߃G[ƂȂB

  "jugemu" +2 "jugemu" 3[ +1 "gokounosurikire" ~5[ +2 "kaijarisuigyono"]];

====================
2.6. K[h

ȏł́AׂẲswq̗DxO[oXR[vLĂB
K[h(guard)pƁADx̃XR[v𕪊lXg邱ƂłB

K[h́AtH[}bg̗"{""}"ň͂ނƂŒ`B

  {"jugemu" +2 "jugemu"} +1 {"gokounosurikire" +2 "kaijarisuigyono"}

ӁFCfgX^bN̑ΉvbVƃ|bvقȂK[hɑĂ͂ȂȂB
ƂΎ̃tH[}bg͐ȂB

  {"jugemu" 2[ +2 "jugemu"} +1 {"gokounosurikire" ] +2 "kaijarisuigyono"}


==========
2.6.1. K[h̃lXg

K[hlXgꍇA͂ޑ̃K[hɑswq́A͂܂鑤̉swq荂DxB

  {{"jugemu" +1 "jugemu"} +1 "gokounosurikire" +2 "kaijarisuigyono"}
  30=>
  jugemu jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̗ł́Aŏ̉swq͗Dx1w肳Ă邪AÕK[hɑswqDxႢB̂߁AÕK[hɑDx12̉swqŉsĂɂ炸ÃK[h̉swqŉsĂȂB

ÕK[hɑswqƁÃK[hɑDswqƂ̊Ԃɂ́AD֌WK肵ĂȂB

  {"jugemu" +d "jugemu" +1 {"gokounosurikire" +1 "kaijarisuigyono"}}
  30=>
  jugemu jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

==========
2.6.2. K[h̕

܊֌WɂȂK[hԂł́AɊ܂܂swq̊ԂɗDx̗D֌W͒`ȂB

  {"jugemu" +2 "jugemu"} +1 {"gokounosurikire" +2 "kaijarisuigyono"}
  30=>
  jugemu jugemu
  gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

ŏ̉swqƎOԖڂ̉swq͕ʂ̃K[hɑĂB
āAOԖڂ̉swqŉsĂ邪Aŏ̉swqł͕KvȂ߉sĂȂB


==========
2.6.3. K[hƊJ

swqł̉s̐擪J́Amɂ́AJ(base column)ƁAK[hŃCfgX^bNɃvbVꂽCfg̍vƂZlɂ茈肳B
K[hɈ͂܂ĂȂꍇAJ0łB

K[hJnƁAK[hJnꂽJʒuK[h̊JƂȂB

  "jugemu" + { "jugemu" 5[ +1 "gokounosurikire" ] ~3[ +1 "kaijarisuigyono" ]}
  30=>
  jugemu jugemu
              gokounosurikire
      kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̗ł́ÃK[h͓Ԗڂ"jugemu"̊JnʒuAȂ킿8ڂJnBāAK[h̊J8ƂȂBK[h̉swqŉsꍇ̐擪J́AꂼA8 + 5 = 13, 8 + (-3) = 5ƂȂB

̗ł́AK[h̑OŃCfgX^bNvbVE|bvĂB

  "jugemu" 3[ +1 { "jugemu" 5[ +1 "gokounosurikire"] ~3[ +1 "kaijarisuigyono"]}]
  30=>
  jugemu
     jugemu
          gokounosurikire
  kaijarisuigyono
  ------------------------------
  123456789012345678901234567890

̏ꍇAK[h͍ŏ̉swqɂsƃCfg̒ォJnAK[h̊J4ƂȂBK[h̉swqŉsꍇ̐擪J́Aꂼ4 + 5 = 9, 4 + (-3) = 1ƂȂB


====================
2.7. s萔

s萔̓obNXbV'n'ŕ\LB
s萔̓V^bNXVK[ƂĂ悢B
s萔́ẨswqDxswqƁAɂÂk̒ȗƂ݂邱ƂłB

  "jugemu" \n "jugemu"
  20=>
  jugemu
  jugemu
  --------------------
  12345678901234567890

̗ł́Aw肳ꂽ20̈sŏo͂łɂ炸AsĂB

  "jugemu" 1 { 4[ "jugemu" +2 "gokounosurikire" \n "kaijarisuigyono" ] }
  50=>
  jugemu
  jugemu gokounosurikire
      kaijarisuigyono
  --------------------------------------------------
  12345678901234567890123456789012345678901234567890

̗Ɍ悤ɁAs萔łň͂ރK[hʂɈʒu邷ׂẲswq̉ӏŉsB
܂As萔ł̉śẢswqƓlɁACfgX^bNɂăCfgB


========================================
3. wq

SMLFormat́AvO~Oꏈnł͍̉\؂̃eLXg\o͏̎⏕vȖړIƂB
̃vO~ÓAvOvf̐eq֌W\[XR[h̃eLXgŐ\ł悤A\vfԂ̐KɉČK`ĂB

SMLFormat́AtH[}bg̏o͌ʂɃvO~ǑK𔽉f邽߂ɃtH[}bgԂ̌͂\wq(assoc indicator)𓱓B

wq́AK[hJnL("{")̒OɌ̕Ƌx̂悤ɋLqĎw肷B

  L10{ "map" + "getContents" + "documents" }
  R5{ "first" + "::" + "second" + "::" + "others" }
  N0{ "if" + "matched" +1 "then" + "Matched" +1 "else" + "Fail" }

'L'̓K[h̗vfԂł邱ƂwB
lɁA'R'͉Eł邱ƂwB
'N'͌lȂƂwB
x͐lŎw肵A傫Ȑl苭x\B
K[hvfԂ̌͂͌ƌx̗猈肳B


====================
3.1. K[h̕ی

SMLFormat́Awqw肳ꂽK[hAKvɉĊʂň͂ށB


==========
3.1.1. eqK[ȟ͂̔r

Ƃ΁AZŽ͂L1AZŽ͂L2ƂAZp̂悤ȃtH[}bgŕ\B

  L2{ L1{ "x" "+" "y" } + "*" + L1{ "v" + "w" }}

̃tH[}bg̏o͌ʂ́A

  x + y * v + w

ł͂ȂA

  (x + y) * (v + w)

ƂׂłB

SMLFormat́AK[hvfԂ̌͂ƁÃK[hvfƂĊ܂ޏʃK[h̗vfԌ͂rāAK[hʂň͂ނׂ肷B
܂AK[hČ͂SƂACO͂ރK[hP̌͂TƂƁASTuアvȂ΁AC̗vfAPCɗאڂvfƌ̂hCʂň͂ޕKvB


==========
3.1.2. ƈʒu֌W

K[hʂň͂ނׂ肷邽߂ɂ́Aeq֌WɂK[ȟ͊Ԃ̋֌WɉāAeK[hł̎qK[ḧʒulɓȂ΂ȂB

Ƃ΁A֐Kp̌͂L10ƂAdɃlXg֐Kp̃tH[}bgŕ\B

  L10{ L10{ "f" + "x" } + L10{ "g" + "y" }}

̃tH[}bg̏o͌ʂ

  f x g y

ł͂Ȃ

  (f x) (g y)

ƂׂłB
ɁAł邱ƂÅ֐Kp͂ފʂ菜

  f x (g y)

Ƃ邱ƂłBAE̊֐Kp͂ފʂ͏ȗłȂB


lɁA֐^\^\q'->'̌͂R1ƂƁAtH[}bg

  R1{ R1{ "t1" + "->" + "t2" } + "->" + R1{ "s1" + "->" + "s2" }}

̏o͌ʂ

  t1 -> t2 -> s1 -> s2

ł͂Ȃ

  (t1 -> t2) -> (s1 -> s2)



  (t1 -> t2) -> s1 -> s2

ƂׂłB


====================
3.2. wq̏

SMLFormat́Aȉɐ菇ɂāAtH[}bǧwqtK[hAwqȂK[hƁAKvȂ΃K[h͂ފʂɕϊB

ʂɂ݂̗͂vsv́AʃK[hupv錋͂ƁAK[hɎw肳ꂽ͂Ƃ̔rɂČ肷B

==========
3.2.1. p錋

ʃK[hpꂽ͂SƂAtH[}bgeƂB
e̎qvfɑ΂Čp錋͂̂悤Ɍ肷B

  e = T{ exp1 ... expk }̏ꍇ
    T = Ln łꍇ
         exp1 ... expk ̃K[h܂͕萔̂łɈʒu鎮
        ɑ΂LnpB
         ̗̑vfɑ΂Ă Nn pB
    T = Rn łꍇ
         exp1 ... expk ̃K[h܂͕萔̂łEɈʒu鎮
        ɑ΂RnpB
         ̗̑vfɑ΂Ă Nn pB
    T = Nn łꍇ
         exp1 ... expk ̂ꂼɑ΂ Nn pB

  e = {exp1 ... expk}̏ꍇ
    S = Ln łꍇ
         exp1 ... expk ̃K[h܂͕萔̂łɈʒu鎮
        ɑ΂LnpB
         ̗̑vfɑ΂Ă Nn pB
    S = Rn łꍇ
         exp1 ... expk ̃K[h܂͕萔̂łEɈʒu鎮
        ɑ΂RnpB
         ̗̑vfɑ΂Ă Nn pB
    S = Nn łꍇ
         exp1 ... expk ̂ꂼɑ΂ Nn pB

  ̑̏ꍇ
    e͎qvfȂ̂Ō͂̌p͕svB


==========
3.2.2. wq'<'֌W

wqł̓񍀊֌W'<'̂悤ɒ`B

     An < Bm, if n < m (A,B are L,R or N)
     Ln < Nn
     Rn < Nn
     p < q, if p < r and r < q

܂A

  p <> q == ((p = Ln and q = Rn) or (p = Rn and q = Ln))

ƒ`B

==========
3.2.3. K[h̕ی

ʃK[hpꂽ͂SAʃK[hɎw肳ꂽwq̌͂TƂƁAʃK[h͂ފʂ̕Kv̂悤ɔfB

  a) S < T ܂ S = T Ȃ΁AK[h͂ފʂ͕svB
  b) ̑AȂ킿 T < S ܂ S <> T łꍇAK[hʂň͂ށB


==========
3.2.4. ϊ

ʃK[hp͂SƂAwqtH[}bge菜ĐVɎe'𓾂邱Ƃ

  S | e => e'

ƕ\LB

ɂO̃tH[}bg̕ϊ菇B
p錋͂̏lƂN0pB

=====
P
 L2{ L1{ "x" "+" "y" } + "*" + L1{ "v" + "w" } }

  L1 < L2                      L1 < N2
  --------------------------   --------------------------
  L2| L1{"x" "+" "y"}          N2| L1{"v" "+" "w"}
    | => "(" {"x" + "y"} ")"     | => "(" {"v" + "w"} ")"   N0 < L2
  -----------------------------------------------------------------
  N0| L2{L1{"x" "+" "y"} + "*" + L1{"v" + "w"}}
    |        => {"(" {"x" + "y"} ")" + "*" + "(" {"v" + "w"} ")"}

=====
Q
 L10{ L10{ "f" + "x" } + L10{ "g" + "y" } }

  L10 = L10             L10 < N10
  -------------------   ---------------------------
  L10| L10{"f" + "x"}   N10| L10{"g" + "y"}
     | => {"f" + "x"}      | => "(" {"g" + "y"} ")"   N0 < L10
  ------------------------------------------------------------
  N0| L10{L10{"f" + "x"} + L10{"g" + "y"}}
    |            => {{"f" + "x"} + "(" {"g" + "y"} ")"}

=====
R
 R1{ R1{ "t1" + "->" + t2" } + "->" + R1{ "s1" + "->" + "s2" } }

  R1 < N1                              R1 = R1
  -------------------------------      ---------------------------
  N1| R1{"t1" + "->" + t2"}            R1| R1{"s1" + "->" + "s2"}
    | => "(" {"t1" + "->" + t2"} ")"     | => {"s1" + "->" + "s2"}  N0 < R1
  -------------------------------------------------------------------------
  N0| R1{R1{"t1" + "->" + t2"} + "->" + R1{"s1" + "->" + "s2"}}
    |       => {"(" {"t1" + "->" + t2"} ")" + "->" + {"s1" + "->" + "s2"}}

==========
3.2.5. cut

SMLlettupleAR[ĥ悤ɑOL[[hLň͂܂Ă鎮́A̎uĂ镶ɂ炸AJbRň͂ޕKvȂB
AOq̌wqł͂̂悤ȏꍇɓK؂Ȍxw肷邱ƂłȂB

ƂāASML̎tH[}bgł킷ƂlB

  f (g x, y)     --(*)

SMLł͊֐Kp͑̎荂xB
āAexp1, exp2ꂼ֐ƈ\tH[}bgƂƁA֐Kp͎̂悤ȃtH[}bgŕ\ƂłB

  L10{ exp1 + exp2 }

ɁAtuple

  N0{ "(" exp1 "," + ... "," + expn ")" }

ł킷ƂɂB
ƁA(*)킷tH[}bg

  L10{ "f" + N0{ "(" L10{ "g" + "x" } "," + "y"")" } }

ƂȂB̃tH[}bgo͂ƁA

                    N0 < L10
                    ---------------------------------
                    N0| L10{ "g" + "x" } => "g" + "x"
                    ------------------------------------------
                    N0| "(" L10{ "g" + "x" } "," + "y" ")"
                      |       => "(" "g" + "x" "," + "y" ")"    N0 < N10
                    ----------------------------------------------------
                    N10| N0{ "(" L10{ "g" + "x" } "," + "y"")" }
  L10| "f" => "f"      |     =>  "(" "(" "g" + "x" "," + "y" ")" ")"
  ------------------------------------------------------------------
  N0| L10{ "f" + N0{ "(" L10{ "g" + "x" } "," + "y"")" } }
    |    => "f" + "(" "(" "g" + "x" "," + "y" ")" ")"

̂悤tuple璷ȃJbRň͂܂Ă܂B

  f ((g x, y))

tuplěx֐Kp̌xア߂łB
ŁAtuple̍\vf̌xN10ɏグ

  N10{ "(" exp1 "," + ... "," + expn ")" }

ƂB(*)킷tH[}bg

  L10{ "f" + N10{ "(" L10{ "g" + "x" } "," + "y"")" } }

ƂȂAo͂ƁA

                    L10 < N10
                    ------------------------------------------
                    N10| L10{ "g" + "x" } => "(" "g" + "x" ")"
                    ------------------------------------------
                    N10| "(" L10{ "g" + "x" } "," + "y" ")"
                       |   => "(" "(" "g" + "x" ")" "," + "y" ")"
                    ---------------------------------------------
                    N10| N10{ "(" L10{ "g" + "x" } "," + "y"")" }
  L10| "f" => "f"      |  =>  "(" "(" "g" + "x" ")" "," + "y" ")"
  ---------------------------------------------------------------
  N0| L10{ "f" + N10{ "(" L10{ "g" + "x" } "," + "y"")" } }
    |    => "f" + "(" "(" "g" + "x" ")" "," + "y" ")"

ɂAtuple̊֐KpJbRň͂܂Ă܂B

  f ((g x), y)

̖́AK[hɎw肳ꂽ͂AʃK[hp錋͂ƉʃK[hɎw肳ꂽ̗͂҂Ɣr邱ƂɌB
邽߁AwqgAʃK[ȟ͂̌pՒf(cut)AK[ȟ͂ʃK[ȟ͂Ƃ̂ݔr邱Ƃwł悤ɂB
擪"!"Ƃ錋wqcuttwqƌĂсA̎wqw肳ꂽK[h͏ʃK[ȟ͂ɂ炸Aʂň͂܂Ȃ̂ƂB

pāAtuple킷tH[}bg

  !N0{ "(" exp1 "," + ... "," + expn ")" }

ƂB

(*)킷tH[}bg

  L10{ "f" + !N0{ "(" L10{ "g" + "x" } "," + "y"")" } }

ƂȂAo͂ʂ́A

                    N0 < L10
                    ---------------------------------
                    N0| L10{ "g" + "x" } => "g" + "x"
                    ------------------------------------------
                    N0| "(" L10{ "g" + "x" } "," + "y" ")"
                      |         => "(" "g" + "x" "," + "y" ")"
                    ---------------------------------------------
                    N10| !N0{ "(" L10{ "g" + "x" } "," + "y"")" }
  L10| "f" => "f"      |     =>  "(" "g" + "x" "," + "y" ")"
  ---------------------------------------------------------------
  N0| L10{ "f" + !N0{ "(" L10{ "g" + "x" } "," + "y"")" } }
    |    => "f" + "(" "g" + "x" "," + "y" ")"

ɂA

  f (g x, y)

ƂȂAsKvȊʂ}ȂB


========================================
4. tH[}b^

SMLFormat́Atype錾datatype錾ɗ^ꂽRgtH[}b^֐R[h𐶐B


====================
4.1. {tH[}b^֐

intstringȂǑgݍ݂邢SML Basis LibraryŒ񋟂{IȌ^ɑ΂ẮA炩BasicFormattersXgN`ɃtH[}b^֐pӂĂB
Ƃint^ɑ΂Ăformat_intAstring^ɑ΂Ăformat_stringpӂĂB

====================
4.2. type錾ɑ΂tH[}bgRg

̂悤type錾

  type number = int

number^`Ǎ^̃tH[}b^`B

SMLFormatɃtH[}b^𐶐邽߂ɂ́A̂悤ɃRgŒ߂^B

  (*%
   *)
  type number =
                 (*%
                  * @format(value) "123"
                  *)
                 int

SMLFormatɑ΂ẃA"(*%""*)"ň͂܂ꂽRgɋLqB
tH[}bgRgƌĂԁB
type錾ɑ΂tH[}bgRg^錾wb_RgA'='̉Eӂ̌^ɑ΂tH[}bgRg`^RgƌĂԁB
̃tH[}bgRǵAtypeL[[hь^ȉꍇ"int"j̒OɔzuȂ΂ȂȂB


==========
4.2.1. ^錾wb_Rg

type錾ɑ΂tH[}b^𐶐邽߂ɂ͌^錾wb_RgKvłB
̗ł͌^錾wb_RgɉLqKv͂Ȃ̂ŋ̃Rg^B


==========
4.2.2. `^Rg

`^wb_Rgɂ́AtH[}bg^OЂƂLqB
tH[}bg^O͈ȉ̌`ƂB

  "@format(" typepat ")" template ... template

typepatɂ́A^ɑ΂p^[LqB^Cvp^[ƌĂԁB

templateɂ́AtH[}bgev[gLqB
tH[}bgev[ǵARgΏۂ̌^̒leLXgo͂ۂ̏w肷B
tH[}bgev[g̍\K̓tH[}bg̍\K܂̂ŁAtH[}bĝ܂܃tH[}bgev[gƂċLqłB

==========
4.2.3. tH[}b^̐

number^ɑ΂SMLFormat͂̂悤ȃtH[}b^R[h𐶐B
̂߁A"<<"">>"ň͂܂ꂽɂ̓tH[}bgSML݂ċLqĂBSMLFormatۂ̃R[hł́A̕ FormatExpression.expression list 𐶐B

  fun format_number x = case x of value => << "123" >>

====================
4.3. datatype錾ɑ΂tH[}bgRg

datatype錾ɑ΂tH[}bgRǵA^錾wb_RgƁAel\qɑ΂`^Rg\B

  (*% *)
  datatype maybeNumber =
                        (*% @format(value) "456" *)
                        SomeNumber of number
                      | (*% @format "none" *)
                        NotNumber

`^Rg̃tH[}bg^Oɂ́Al\q̂Ƃ̌^ɑ΂^Cvp^[ƁAev[gLqB
ƂȂl\qɑ΂tH[}bg^Oł́A^Cvp^[͕svłB

SMLFormat́AmaybeNumberɑ΂Ă̃tH[}b^𐶐B

  fun format_maybeNumber x =
      case x of
          SomeNumber value => << "456" >>
        | NotNumber => << "none" >>


====================
4.4. ^Cvp^[

SMLFormat́AtH[}bg^Õ^Cvp^[A`^̒lƂ̃p^[}b`ȂR[h𐶐B
܂A^ƃ^Cvp^[Ƃ̏ƍɂA^Cvp^[̎ʎqɑΉ^łB

^Cvp^[Ɍ鎯ʎq́AtH[}bgev[gŎgp邱ƂłB
tH[}bgev[g̎ʎq́Asɂ̎ʎqɑl̃tH[}bg\𐶐R[hɕϊB
܂Aev[gɌ鎯ʎq́AɑΉ^ɑ΂Ē`Ăev[g̈ʒuɓWJ邱ƂɑB̂߁Aev[g̎ʎq̏oAev[gCX^VG[V(template instantiation)ƌĂԁB

ev[gCX^VG[VgpāAnumber^ɑ΂tH[}bgRg̂悤ɕύXB

  (*% *)
  type number =
                 (*% @format(value) value *)
                 int

SMLFormat͂̃tH[}b^𐶐B

  fun format_number x = case x of value => << format_int(value) >>

^ƃ^Cvp^[̏ƍɂ莯ʎqvalueɂ͌^intΉ̂ŁAev[gɏo鎯ʎqvaluéAint^̃tH[}b^(format_int)ĂяoR[hɕϊB

maybeNumberlɕύXB

  (*% *)
  datatype maybeNumber =
                        (*% @format(value) value *)
                        SomeNumber of number
                      | (*% @format "none" *)
                        NotNumber

  fun format_maybeNumber x =
      case x of
          SomeNumber value => << format_number(value) >>
        | NotNumber => << "none" >>


==========
4.4.1. ʎq^p^[

ʎq͂̌^Ƃ}b`^Cvp^[ƂĎgpłB


==========
4.4.2. tuple^p^[

tuple^ɑ΂ẮA̂悤Ƀ^Cvp^[w肷邱ƂłB

  (*% *)
  type region =
               (*% @format(left * right) "left=" left + "right=" right *)
               int * int

SMLFormat́Aregion^ɑ΂Ă̃tH[}b^𐶐B

  fun format_region x =
      case x of
          (left, right) =>
              << "left=" format_int(left) + "right=" format_int(right) >>


==========
4.4.3. R[h^p^[

R[h^ɂĂlłB

  (*% *)
  type range =
               (*% @format({min : minimum, max}) minimum + "<->" + max *)
               {min : int, max : int}

SMLFormat́Arange^ɑ΂Ă̃tH[}b^𐶐B

  fun format_range x =
      case x of
          {min = minimum, max} =>
              << format_int(minimum) + "<->" + format_int(max) >>


==========
4.4.4. Ƃ^\q

SMLFormat́Alist̂悤ɈƂ^\qɑ΂ĂtH[}b^𐶐łB

  (*% *)
  datatype 'a maybe =
                     (*% @format(value) value *)
                     Something of 'a
                   | (*% @format "none" *)
                     Nothing

maybeɑ΂SMLFormattH[}b^́A^ϐ'aɑ΂tH[}b^ɂƂBtH[}b^ƌĂԁB

  fun format_maybe format_'a x =
      case x of
          Something value => << format_'a(value) >>
        | Nothing => << "none" >>


maybeKp^ɑ΂tH[}bgRg͂̂悤ɋLqB

  (*% *)
  type maybeString =
                (*% @format(str tycon) tycon(str) *)
                string maybe

^\qKpɑ΂^Cvp^[́A
  typepat ID
Ƃ`ƂB
̗ł́Aʎqtyconɂ͌^\qmaybe}b`Ap^[strɂ͌^string}b`B

ev[gł́A^\qɃ}b`鎯ʎqւ̈ɁA^\qւ̈Ƀ}b`鎯ʎq^`ŋLqB
̗ł́Atyconւ̈Ƃstr^`ƂȂB

⑫F`^݂΁AʎqtyconɃ}b`maybeɂstringƂė^Ă邱Ƃ͖炩łBāAev[g
    tycon(str)
̂悤tyconɑ΂strw肷̂͏璷ł悤ɎvB
ÁAɐǉ𓱓ʁAǉǂ̎ʎqɗ^̂Ή𖾂炩ɂKv߂̐łB

maybeStringɑ΂tH[}b^́A̂悤format_maybȇƂformat_string^B

  fun format_maybeString x =
      case x of tycon => << (format_maybe format_string tycon) >>


==========
4.4.5. ChJ[h^p^[

 '_'ChJ[hƂĎgƂłB

  (*% *)
  type wildCard =
                  (*% @format(_ * n) n *)
                  (bool * int) 

ChJ[h^p^[́A^[ɑ΂郏ChJ[hp^[ɕϊB

  fun format_wildCard  x = 
      case x of
          (_, n) => 
          << format_int(n) >>


==========
4.4.6. ptʎqAx

ʎq⃉x'd'邢͐łꍇAswqƂĉ߂邱Ƃh߁Adpň͂܂Ȃ΂ȂȂB

  (*% *)
  type quotedFields =
                    (*% @format({'d' : fd, '1' : f1}) fd f1 *)
                    {d : int, 1 : bool}

smlformat͎̃tH[}b^𐶐B

  fun format_quotedFields  x = 
      case x of
           {d = fd, 1 = f1} => 
               << format_int(fd) format_bool(f1) >>


==========
4.4.7. ǉ

tH[}b^́AtH[}bgΏۂ̒ltH[}b^̂قɒǉƂ邱ƂłB

  (*%
   * @params (label)
   *)
  type 'a anyLabeled =
                      (*% @format(value) label ":" value *)
                      'a

ǉ̖ÓA^錾wb_Rg"@params"^OŎw肷B
ǉKvȏꍇA

  (*%
   * @params (p1, ..., pk)
   *)

邢

  (*%
   * @params (p1)
   *     :
   * @params (pk)
   *)

̂悤ɋLqB

ǉ̓ev[gŎgpłB
ev[gɏoǉ́Asɂ́AtH[}b^ɑ΂ČĂяontH[}bgev[gɒuB

anyLabeledɑ΂āASMLFormat͂̃tH[}b^𐶐B

  fun format_anyLabeled (format_'a, label) x =
      case x of value => << label ":" format_'a(value) >>


^\qT̃tH[}b^ǉƂꍇATɃ}b`鎯ʎqev[gŎgpۂɂ́AtH[}b^Ƃ͕ʂɁAǉw肵Ȃ΂ȂȂB
Cӂ̃ev[gǉœnƂłB
tH[}b^j̃tH[}b^k̒ǉƂꍇA̍\gpB

  ID(inst1, ..., instj)(temp1, ..., tempk)

tH[}b^ǉƂȂꍇÅʂ͕svłB

  ID(inst1, ..., instj)

tH[}b^tH[}b^Ƃ炸AǉƂꍇ́A

  ID()(temp1, ..., tempk)

ƂȂ΂ȂȂB

ӁFSMLFormat͌ĂяotH[}b^̌^𔻒łȂ̂ŁAvO}ĂяõR[hŃtH[}b^ƒǉʂ̊ʂɕ邱ƂɂAʂł悤ɂB

ƂanyLabeledgp鑤͂̂悤ɒǉnB

  (*% *)
  type intLabeled =
                      (*% @format(num tycon) tycon(num)("INT") *)
                      int anyLabeled

̂悤ȃtH[}b^B

  fun format_intLabeled x =
      case x of tycon => << format_anyLabeled (format_int, "INT") tycon >>

ӁFSMLFormat̓tH[}b^vǉev[gŎw肳ĂȂĂG[ƂȂBSMLFormatR[hRpCۂɃG[ƂȂ͂łB


====================
4.5. `I`

ŁA܂łɐtH[}b^̌`IȒ`B


==========
4.5.1. 

tH[}b^ F ^\qtH[}b^֐ւ̃}bvƂBi'int''string'Ȃǂ͈[̌^\qƂ݂ȂBj

^ T ʎq^ւ̃}bvƂB

ǉW P ǉ̏WƂB


==========
4.5.2. tH[}bgev[gϊ

F,T,P̂ƂŃtH[}bgev[gtemp tH[}bgSML̍exp 𓾂邱Ƃ̂悤ɏB

  F,T,P | temp ==> exp

eev[gɑ΂KȉɎB

(STRING)
    F,T,P | "string" ==> "string"
  
(INDICATOR)
    F,T,P | sp ==> sp

(INDSTART)
    F,T,P | ind[ ==> ind[

(INDEND)
    F,T,P | ] ==> ]

(SEQ)
    F,T,P | templ1 ==> exp1    F,T,P | templ2 ==> exp2
    --------------------------------------------------
    F,T,P | templ1 templ2 ==> exp1 exp2

(GUARD)
    F,T,P | temp ==> exp
    ---------------------------
    F,T,P | { temp } ==> { exp }

(INST1)
    T(ID) = (t1,...,tj) t    T(ID1) = t1   ...  T(IDj) = tj
    F(t) = f    F(t1) = f1  ...  F(tj) = fj
    F,T,P | temp1 ==> exp1
          :
    F,T,P | tempk ==> expk
    -------------------------------------------------------
    F,| ID(ID1,...,IDj)(temp1,..., tempk)
    T,|        ==>
    P |         f(f1, ..., fj, exp1, ... , expk)(ID)

    i̋KŐ̂SML̊֐KpłBj

(INST2)
    T(ID) = t         F(t) = f
    --------------------------
    F,T,P | ID    ==>   f(ID)

    i̋KŐ̂SML̊֐KpłBj

(INST3)
    P = P'+{ID}
    ---------------------
    F,T,P | ID   ==>   ID

    i̋KŐ̂SML̕ϐłBj


==========
4.5.3. tH[}b^{̂̐

ɁAF,P̂ƂŃtH[}bg^Oƕϐ xь^ teASMLe𓾂ϊ

  F,P | @format(typepat) template, x, te  ==> e

ƏB
̋K̈Ӗ́Ax̓tH[}bgΏۂ̒lێϐłAx̌^teAtH[}bg^Oteɑ΂鏑ŵłB

tetuple^܂͌^\qKp^łꍇɂĂ̋KB
R[h^ɂĂ͏ȗB
'int''string'Ȃǂ̊{^͈[̌^\qKp^ƂĈB

(TUPLEtype)
    dom(F) includes {t1,...,tj}
    T = {ID1:t1, ..., IDj:tj}
    F,T,P | temp => e
    -------------------------------------------------
    F,| @format(ID1 * ... * IDj) temp,
    P | x, (t1 * ... * tj)
      |              ==> case x of (ID1,...,IDj) => e

(TYCONAPPtype)
    dom(F) includes {t,t1,...,tj}
    T = {ID:(t1,...,tj)t, ID1:t1, ..., IDj:tj}
    F,T,P | temp => e
    --------------------------------------------------
    F,| @format((ID1, ..., IDj) ID) temp,
    P | x, (t1, ..., tj) t 
      |                          ==> case x of ID => e


==========
4.5.4. tH[}b^̐

ȏpāAF̂ƂŁASMLtype錾datatype錾AtH[}b^֐̃R[hƐVȃtH[}b^F'𓾂菇̋KŎB

ł́AЂƂ̌^\qtype錾datatype錾Œ`̂ƂB
i'and'ɂĕ̌^AĒ`ꍇɑΉ̂͗eՂłBj


(TYPEdec)
    x,f1,...,fj are fresh variables
    F' = F+{t:format_t}
    F'' = F'+{'a1:f1, ..., 'aj:fj}
    P = {b1,...,bk}
    F'',P | formattag,x,t  ==>  e
    -------------------------------------------------------
    F | (*% @formatparams (b1,...,bk) *)
      | type ('a1,...,'aj) t =
      |         (*% formattag *) t
      |    ==>
      |            fun format_t(f1,...,fj,b1,...,bk) x = e,
      |            F'

(DATATYPEdec)
    x,x1,...,xj,f1,...,fj are fresh variables
    F' = F+{t:format_t}
    F'' = F'+{'a1:f1, ..., 'aj:fj}
    P = {b1, ..., bk}
    F'',P | formattag1,x1,t1  ==> e1
             :
    F'',P | formattagj,xj,tj  ==> ej
    -----------------------------------------------------
    F | (*% @formatparams (b1,...,bk) *)
      | datatype ('a1,...,'aj) t =
      |           (*% formattag1 *)  D1 of t1
      |         | ...
      |         | (*% formattagj *)  Dj of tj 
      |    ==>
      |      fun format_t(f1,...,fj,b1,...,bk) x =
      |          case x of D1 x1 => e1 | ... | Dj xj => ej,
      |      F'

l\qƂȂꍇɊւĂ͏ȗB


====================
4.6. Gȃp^[

܂łɎł́A^\qւ̈Atuple^⃌R[h^̗vf̌^͂ЂƂ̎ʎq݂̂琬PȂ̂łB
SMLFormat́A蕡GȌ^ƂłB


==========
4.6.1. lXg^ɑ΂p^[

܂AlXg^\qKp^A܂^\q̈Ɍ^\qKpł^ɑ΂tH[}b^`łB

  (*% *)
  type maybeLabeledInt =
                        (*%
                         * @format(num may any) any(may(num))("INT")
                         *)
                        int maybe anyLabeled

maybeLabeledInt̃tH[}b^͂̂ƂB

  fun format_maybeLabledInt x =
      case x of
         any =>
           << format_anyLabeled (format_maybe format_int, "INT") any >>


tuple^уR[h^̗vfAtuple^邢̓R[h^A^\qKp^łꍇtH[}b^`\łB
maybeRangéAR[h^̗vfɌ^\qKp^łB

  (*% *)
  type maybeRange =
       (*%
        * @format({min : min minMaybe, max : max maxMaybe})
        *       minMaybe(min) "<->" maxMaybe(max)
        *)
       {min : int maybe, max : int maybe}

  fun format_maybeRange x =
      case x of
        {min = minMaybe, max = maxMaybe} =>
         <<
          (format_maybe format_int minMaybe) "<->"
          (format_maybe format_int maxMaybe)
         >>


==========
4.6.2. ^ƎʎqƂ̃}b`

܂ł̗ł́A^Cvp^[̎ʎq́AƍΏۂ̌^intstringȂǂ̒P^maybeȂǂ̌^\qƂ̂݃}b`ĂB
tH[}bgev[g̍\ł́AʎqɃR[h^^\qKp^ȂǕ^}b`ꍇɁÃtH[}bg@Lq邱ƂłȂB

ƂāAtype錾ɑ΂ătH[}b^`邱ƂlB

  (*% *)
  type labeledRange =
       (*%
        * @format(range any) any(range) <== ???
        *)
       {min : int, max : int} anyLabeled

ʎqrangeɃR[h^}b`邪ÃR[h^̒lɑ΂tH[}bg@LqAanyLabeled̃tH[}b^ɓniȂB

̐@ƂẮA̂悤ɕtype/datatype錾ɕ邱ƂlB

  type range = {min : int, max : int}

  type labeledRange = range anyLabeled

A̕@͔ώGłB


==========
4.6.3. [JtH[}bg^O

L̖ɑ΂āASMLFormatł́A^Ƀ}b`鎯ʎqA̕^ɑ΂ĈꎞIɗ^ꂽ^ƂĈǍ^ɑ΂tH[}bgwA`^Rg̕ʂ̃tH[}bg^OŒ`ł悤ɂĂB

̃tH[}bg^OA[JɌ^錾Aɑ΂tH[}bgLqƂӖŁA[JtH[}bg^OƌĂԁB
[JtH[}bg^Oɑ΂āA`^ɑ΂tH[}bg^OvC}tH[}bg^OƌĂԁB

[JtH[}bg^ÓA

  "@format:"ID "(" typepat ")" template ... template

Ƃ`ŋLqBi"@format:"ID̊Ԃɂ͋󔒂ł͂ȂȂBj

[JtH[}bg^OpāAقǂlabeledRangeɑ΂āA̂悤ɃtH[}bgRgLqłB

  (*% *)
  type labeledRange =
       (*%
        * @format(range any) any(range)("Range:")
        * @format:range({min : min, max : max})
        *         "(min =" + min "," + "max =" + max ")"
        *)
       {min : int, max : int} anyLabeled

SMLFormat́AvC}tH[}bg^Õ^Cvp^[

  range any

ƒ`^

  {min : int, max : int} anyLabeled

Ƃ̃p^[}b`Aʎqrange^{min : int, max : int}Ɣ肷B
܂Ả̃[JtH[}bg^ÓAʎqrangeA^Cvp^[

  {min : min, max : max}

ƃ}b`^wOƂĈƂwB
SMLFormat́A𑍍āA[JɈȉ̂悤ɐ錾ꂽ̂Ƃ݂ȂB

  type range = {min : int, max : int}

āAvC}tH[}bg^O̎ʎqrangerange^̂ƂĈArange^ɑ΂tH[}b^[JtH[}bg^O琶B


SMLFormat́ÃtH[}bgRg̃tH[}b^֐𐶐B

  fun format_labeledRange x =
      let
        fun format_range x =
            case x of
              {min = min, max = max} =>
              <<
                "(min =" + format_int(min) "," +
                "max =" + format_int(max) ")"
              >>
      in
        case x of
          any => format_anyLabeled (format_range, "Range:") any
      end

lɁAtree^ɂ[JtH[}bg^OgpătH[}bgRgLq邱ƂłB

  (*% *)
  datatype tree =
                 (*% @format(num) num *)
                 Leaf of int
               | (*%
                  * @format(child children) "{" children(child)(", ") "}"
                  * @format:child({child, label}) label "=" child
                  *)
                 Node of {child : tree, label : string} list

̃tH[}b^B

  fun format_tree x =
      case x of
          Leaf x => case x of num => << (format_int num) >>
        | Node x =>
          let
            fun format_child x =
                case x of
                    {child, label} =>
                    << (format_string label) "=" (format_tree child) >>
          in
            case x of
                children =>
                << "{" (format_list(format_child, ", ") children) "}" >>
          end


lXg^\qKp^ɂĂlɃ[JtH[}bg^Ogp邱ƂłBقǂmaybeLabeledIntȉ̂悤ɏƂłB

  (*% *)
  type maybeLabeledInt =
                        (*%
                         * @format(maybeNum any) any(maybeNum)("INT")
                         * @format:maybeNum(num may) may(num)
                         *)
                        int maybe anyLabeled

̃tH[}b^B

  fun format_maybeLabledInt x =
      case x of
         any =>
           let
             fun format_maybeNum x =
                 case x of may => format_maybe format_int may
           in
             << format_anyLabeled (format_maybeNum, "INT") any >>
           end


ӁFtH[}bg^ÓAׂ鏇ɊւĂ̐ɂȂ΂ȂȂB
`^ɑ΂tH[}bgRgŁAtH[}bg^O

  @format( typepat0 ) ...
  @format:ID1( typepat1 ) ...
       :
  @format:IDk( typepatk ) ...

̏ɕłƂAIDi (1 <= i <= k)́Atypepat0 ... typepat(i-1)̂ꂩɏoĂȂ΂ȂȂB
ƂɁAvC}tH[}bg^O[JtH[}bg^OɋLq邱ƂKvłB


====================
4.7. JX^tH[}b^

tH[}bgRǵAꂼtype/datatype錾ɂĈ񂵂LqłȂB܂AintstringȂǃVXe⃉CuŒ`Ă^ɑ΂ătH[}bgRgLq邱ƂłȂB

SMLFormat́A^ɑ΂Ăłɒ`ĂtH[}b^ɑւĕʂ̃tH[}b^gpAVXe⃉CuȂǂŒ`Ă^ɑ΂tH[}b^w肷ipӂĂBJX^tH[}b^ƌĂԁB

Ƃ΁Awordl2i\LŃtH[}bgtH[}b^MyFormattersXgN`ɒ`ABasicFormatters.format_wordɑւĈꕔłgpƂB

  fun myformat_binary x = << "0b" (Word.fmt StringCvt.BIN x) >>

type/datatype錾̃tH[}bgRgŃJX^tH[}b^gpɂ́A錾wb_Rgɂ̃^OpĎw肷B

  @formatter(ID) qid

̃^ÓAID[IȌ^ƂĐ錾Ǎ^ɑ΂tH[}b^Ƃqidw֐gp邱ƂwB
ȂAqid͂̐KɂB

  qid ::= ID
       |  ID "." qid

āA`^RgŁAʎqɑ΂ĎgpJX^tH[}b^w肷B^Cvp^[Ŏw肷@ƁAev[gŎw肷@̓ʂŎwłB

B

  (*%
   * @formatter(binary) MyFormatters.myformat_binary
   *)
  type file =
             (*%
              * @format({name, flags : flags:binary})
              *           "{name=" name "," + "flags=" flags "}"
              *)
             {name : string, flags : word}

邢͂̂悤ɂB

  (*%
   * @formatter(binary) MyFormatters.myformat_binary
   *)
  type file =
             (*%
              * @format({name, flags})
              *           "{name=" name "," + "flags=" flags:binary "}"
              *)
             {name : string, flags : word}

file^ɑ΂āA̃tH[}b^B

  fun format_file x =
      case x of
        {name, flags} =>
          <<
            "{name=" (format_string name) "," +
            "flags=" (MyFormatters.myformat_binary flags) "}"
          >>


====================
4.8. `I`

lXg^Cvp^[A[JtH[}bg^OAJX^tH[}b^T|[g邽߁A`I`gB


==========
4.8.1. p^[}b`


܂A^tƃ^Cvp^[tp^T𓾂K

    t <=> tp ==> T

`B

(IDmatch)
    t <=> ID ==> {ID:t}

(TypedIDmatch)
    t <=> ID1 : ID2 ==> {ID1:ID2}

(TYCONAPPmatch)
    t1 <=> p1 ==> T1  ...  tj <=> pj ==> Tj
    ----------------------------------------
    (t1, ..., tj) t <=> (p1, ..., pj) ID
          ==> T1+...+Tj+{ID:(t1, ..., tj) t}

(TypedTYCONAPPmatch)
    t1 <=> p1 ==> T1  ...  tj <=> pj ==> Tj
    ----------------------------------------
    (t1, ..., tj) t <=> (p1, ..., pj) ID1 : ID2
          ==> T1+...+Tj+{ID1:(t1, ..., tj) ID2}

(TUPLEmatch)
    t1 <=> p1 ==> T1  ...  tj <=> pj ==> Tj
    -------------------------------------------
    (t1, ..., tj) <=> (p1,... pj) ==> T1+...+Tj


==========
4.8.2. SMLp^[̐

ɁA^Cvp^[typatASML̃p^[expat𓾂K

    typat --> expat

B

(IDpat)
    ID --> ID

(TypedIDpat)
    ID1 : ID2 --> ID1

(TYCONAPPpat)
    (tp, ..., tp) ID --> ID

(TypedTYCONAPPpat)
    (tp, ..., tp) ID1 : ID2 --> ID1

(TUPLEpat)
    tp1 --> pat1    ...    tpj --> patj
    ----------------------------------------
    (tp1 * ... * tpj) -->  (pat1, ..., patj)


==========
4.8.3. tH[}bgev[gϊ

INST1CƂƂɁATypedINST1ATypedINST2ǉB

(INST1)
    T(ID) = (t1,...,tj) t
    F(t) = f
    F,T,P | inst1 ARG==> f1
           :
    F,T,P | instj ARG==> fj
    F,T,P | temp1 ==> exp1
           :
    F,T,P | tempk ==> expk
    -----------------------------------------------
    F,| ID(inst1,...,instj)(temp1,..., tempk)
    T,|       ==>
    P |        f(f1, ..., fj, exp1, ... , expk)(ID)

(TypedINST1)
    F(ID2) = f
    F,T,P | inst1 ARG==> f1
           :
    F,T,P | instj ARG==> fj
    F,T,P | temp1 ==> exp1
           :
    F,T,P | tempk ==> expk
    -----------------------------------------------
    F,| ID1:ID2(inst1,...,instj)(temp1,..., tempk)
    T,|      ==>
    P |       f(f1, ..., fj, exp1, ... , expk)(ID1)

(TypedINST2)
    F(ID2) = f
    --------------------------
    F,T,P | ID1:ID2  ==>  f(ID1)


INST1TypedINST1́Aev[gCX^VG[VtH[}b^֐ւ̕ϊ

    F,T,P | inst ARG==> formatter

pB̕ῗ̎lK琬B

(INST1-ARG)
    T(ID) = (t1,...,tj) t
    F(t) = f
    F,T,P | inst1 ARG==> f1
           :
    F,T,P | instj ARG==> fj
    F,T,P | temp1 ==> exp1
           :
    F,T,P | tempk ==> expk
    --------------------------------------------
    F,| ID(inst1,...,instj)(temp1,..., tempk)
    T,|        ARG==>
    P |         f(f1, ..., fj, exp1, ... , expk)

(TypedINST1-ARG)
    F(ID2) = f
    F,T,P | inst1 ARG==> f1
           :
    F,T,P | instj ARG==> fj
    F,T,P | temp1 ==> exp1
           :
    F,T,P | tempk ==> expk
    -----------------------------------------------
    F,| ID1:ID2(inst1,...,instj)(temp1,..., tempk)
    T,|         ARG==>
    P |            f(f1, ..., fj, exp1, ... , expk)

(INST2-ARG)
    T(ID) = t    F(t) = f
    ---------------------
    F,T,P | ID  ARG==>  f

(TypedINST2-ARG)
    F(ID2) = f
    -------------------------------
    F,T,P | ID1:ID2  ARG==>  f(ID1)


==========
4.8.4. tH[}b^{̂̐


ȏpƁAOɎ(TUPLEtype)(TYCONAPPtype)͂̋KɓłB

(TYPEtype)
    t <=> typepat ==> T
    T(ID1) <=> typepat1 ==> T1
    (T+T1)(ID2) <=> typepat2 ==> T2
         :
    (T+T1+...+Tj-1)(IDj) <=> typepatj ==> Tj
    Fj = F                            (* register formatters for alias type *)
    Fj-1 = Fj+{IDj:fj}
         :
    F1 = F2+{ID2:f2}
    F0 = F1+{ID1:f1}
    T' = T+{ID1:ID1,...,IDj:IDj}    (* overwrites entries for alias type *)
    T1' = T1+{ID2:ID2,...,IDj:IDj}
         :
    Tj' = Tj
    F0,T',P | templates ==> exp       (* generate exps for templates *)
    F1,T1',P | templates1 ==> exp1
         :
    Fj,Tj',P | templatesj ==> expj
    typepat --> pat
    typepat1 --> pat1
         :
    typepatj --> patj
    -----------------------------------------------------
    F, | @format(typepat) templates
    P  | @format:ID1(typepat1) templates1
       |       :
       | @format:IDj(typepatj) templatesj
       | x, t
       |
       |     ==>
       |
       |       case x of pat => let fun fj patj = expj
       |                               :
       |                            fun f1 pat1 = exp1
       |                        in exp end


==========
4.8.5. tH[}b^̐

TYPEdecDATATYPEdecA錾wb_Rgł̃JX^tH[}b^^OɑΉĊgB

TYPEdec,DATATYPEdeĉA`^ɑ΂tH[}b^R[h𐶐ۂɎgptH[}b^ɁAJX^tH[}b^^OŎw肳ꂽtH[}b^B

(TYPEdec)
    x,f1,...,fj are fresh names
    F' = F+{t:format_t}
    F'' = F'+{'a1:f1, ..., 'aj:fj}+{ID1:qid1, ..., IDn:qidn}
    P = {b1,...,bk}
    F'',P | formattag,x,t  ==>  e
    -------------------------------------------------------
    F | (*%
      |    @formatparams (b1,...,bk)
      |    @formatter(ID1) qid1
      |          :
      |    @formatter(IDn) qidn
      |  *)
      | type ('a1,...,'aj) t =
      |         (*% formattag *) t
      |    ==>
      |            fun format_t(f1,...,fj,b1,...,bk) x = e,
      |            F'

(DATATYPEdec)
    x,x1,...,xj,f1,...,fj are fresh names
    F' = F+{t:format_t}
    F'' = F'+{'a1:f1, ..., 'aj:fj}+{ID1:qid1, ..., IDn:qidn}
    P = {b1, ..., bk}
    F'',P | formattag1,x1,t1  ==> e1
             :
    F'',P | formattagj,xj,tj  ==> ej
    -----------------------------------------------------
    F | (*%
      |    @formatparams (b1,...,bk)
      |    @formatter(ID1) qid1
      |          :
      |    @formatter(IDn) qidn
      |  *)
      | datatype ('a1,...,'aj) t =
      |           (*% formattag1 *)  D1 of t1
      |         | ...
      |         | (*% formattagj *)  Dj of tj 
      |    ==>
      |      fun format_t(f1,...,fj,b1,...,bk) x =
      |          case x of D1 x1 => e1 | ... | Dj xj => ej,
      |      F'


====================
4.9. ftHgtH[}bg^O

^錾wb_Rgw肳Ăɂ炸A`^ɒ`^Rgw肳ĂȂꍇASMLFormat͂̒`^ɑ΂ătH[}bg^OBftHgtH[}bg^OƌĂԁBāÃ^OƂɁAvO}IɃ^Ow肵ꍇƓlɁAtH[}b^R[h𐶐B

Ƃ΁A̂悤Ɍ^\qmaybe`Ăꍇ

  (*% *)
  datatype 'a maybe =
                     Something of 'a
                   | (*% @format "none" *)
                     Nothing

SMLFormat́Al\qSomethingɑ΂Ă̂悤ȃftHgtH[}bg^O𐶐ŃtH[}b^R[h𐶐B

  (*% *)
  datatype 'a maybe =
                     (*% @format(x1) {"Something" + {x1}} *)
                     Something of 'a
                   | (*% @format "none" *)
                     Nothing

ftHgtH[}bg^OɂĐtH[}b^́AtH[}bgΏۂ̒lASML̃\[XR[hŋLqꍇƓľ`ɃtH[}bgB
Ƃ {name : string, age : int} ^̒l {name = "YAMADA", age = 20} 
  {name = "YAMADA", age = 20}
Əo͂Aint list^̒l [1, 3, 5] 
  [1, 3, 5]
Əo͂B

ftHgtH[}bg^O̐KȉɎB
̋ḰA^tAЂƂ̃vC}tH[}bg^Oj̃[JtH[}bg^ÕXg𐶐邱Ƃ

  t => (typat, temps), {(id1, typat1, temps1), ..., (idj, typatj, tempsj)}

̂悤ɕ\LB
vC}^O̓^Cvp^[typatƃev[gtemps\B
[JtH[}bg^ÓAʎqA^Cvp^[Aev[g񂩂\B

(ATOMdeftags)
    x is fresh name
    ---------------
    ID
    =>
    (x, x), {}

(TUPLEdeftags)
    x1,...,xj are fresh names
    t1 => ((typat1, temp1), L1)
         :
    tj => ((typatj, tempj), Lj)
    ---------------------------------------------------------
    t1 * ... * tj
    =>
    ((x1, ..., xj), "(" x1 "," ... "," xj ")"),
    {(x1, typat1, temp1), ..., (xj, typatj, tempj)}+L1+...+Lj

(RECORDdeftags)
    x1,...,xj are fresh names
    t1 => ((typat1, temp1), L1)
         :
    tj => ((typatj, tempj), Lj)
    -----------------------------------------------------------------------
    {ID1:t1, ..., IDj:tj}
    =>
    ({ID1=x1, ..., IDj=xj}, "{" "ID1" "=" x1 "," ... "," "IDj" "=" xj "}"),
    {(x1, typat1, temp1), ..., (xj, typatj, tempj)}+L1+...+Lj

(TYCONAPPdeftags)
    x1,...,xj are fresh names
    t1 => ((typat1, temp1), L1)
         :
    tj => ((typatj, tempj), Lj)
    ---------------------------------------------------------
    (t1, ..., tj) ID
    =>
    ((x1, ..., xj) x, x(x1, ..., xj)),
    {(x1, typat1, temp1), ..., (xj, typatj, tempj)}+L1+...+Lj

tList.listKp^\qKp^łꍇ́Aǉlistp̃tH[}b^(BasicFormatters.format_list)ɓnKv̂ŋKʂɐ݂B

(listAPPdeftags)
    x1,...,xj are fresh names
    t1 => ((typat1, temp1), L1)
         :
    tj => ((typatj, tempj), Lj)
    ---------------------------------------------------------
    (t1, ..., tj) list
    =>
    ((x1, ..., xj) x, "[" x(x1, ..., xj)(",") "]"),
    {(x1, typat1, temp1), ..., (xj, typatj, tempj)}+L1+...+Lj

tArray.arrayVector.vectorKp^\qKp^łꍇlłB

t֐^łꍇ́Alp^[}b`ɂĂȏ͂邱ƂłȂ̂ŁAŒ̕萔o͂B

(funAPPdeftags)
    x is a fresh name.
    --------------
    t1 -> t2
    =>
    (x, "<<fn>>"),
    {}

type錾̒`^ɂẮAȏ̋KœvC}tH[}bg^Ô܂܎gpB
datatype錾̒`^ɂẮAȏ̋KœvC}tH[}bg^Õev[g̐擪ɁAl\q̖O}ŎgpB

====================
4.10. ^錾

==========
4.10.1. ݍċAdatatype

ЂƂdatatype錾andɂAĐ錾ꂽ̃f[^^ɑ΂ẮAݎQƂtH[}b^R[hB

==========
4.10.2. withtype

withtypep^錾ɑ΂ĂtH[}bgRgLqłB


  (*% *)
  datatype tree =
                 (*% @format(num) num *)
                 Leaf of int
               | (*% @format(child children) "{" children(child)(", ") "}" *)
                 Node of node list

  withtype node =
                 (*% @format({child, label}) label "=" child *)
                 {child : tree, label : string}

̃tH[}b^B

  fun format_tree x =
      case x of
          Leaf x => case x of num => << (format_int num) >>
        | Node x =>
          case x of
              children =>
              << "{" (format_list(format_node, ", ") children) "}" >>
  and format_node x =
      case x of
          {child, label} =>
              << (format_string label) "=" (format_tree child) >>

==========
4.10.3. abstype

abstypeɂĂtH[}bgRgLqłB

    (*% *)
    abstype set =
            (*% @format(element elements) "{" elements(element)(", ") "}" *)
            SET of element list
    withtype element =
             (*% @format(value) value *)
             string
    with
      fun create () = ...
      fun addTo (v, set) = ...
      fun isMemberOf (v, set) = ...
    end

܂łɂ݂^錾ł̓tH[}b^R[h͐錾̒ɐĂAabstypeɑ΂Ă̓tH[}b^R[h͂̂悤ɐ錾ɐB

    (*% *)
    abstype set =
            (*% @format(element elements) "{" elements(element)(", ") "}" *)
            SET of element list
    withtype element =
             (*% @format(value) value *)
             string
    with
      fun format_set x = ...
      and format_element x = ...
      fun create () = ...
      fun addTo (v, set) = ...
      fun isMemberOf (v, set) = ...
    end

====================
4.10.4 datatype replication

  datatype s = datatype M.t

̌`Œ`f[^^ɂẮA̂悤ɃtH[}b^w肷B

    (*%
     * @formatter(Absyn.region) Absyn.format_region
     *)
    datatype region = datatype Absyn.region


====================
4.12. exception錾

O\qɑ΂ĂtH[}bgRgLqłB
  
  (*% *)
  exception
  (*%
   * @format({fileName, line : leftLine, col : leftCol} *
   *         {line : rightLine, col : rightCol, ...} *
   *         message)
   * fileName ":" leftLine "." leftCol "-" rightLine "." rightCol ":" message
   *)
  ParseError of
  {fileName:string, line:int, col:int} *
  {fileName:string, line:int, col:int} *
  string

O\qg\ł邽߁AO\qɑ΂ĐtH[}b^́Aȉ̂悤ɁAdatatype錾type錾ɑ΂ĐtH[}b^Ƃ͈قȂB

  local
    fun format x =
        case x of
          ParseError
          (
            {fileName, line = leftLine, col = leftCol},
            {line = rightLine, col = rightCol, ...},
            message
          ) =>
           <<
             (format_string fileName) ":"
             (format_int leftLine) "." (format_int leftCol) "-"
             (format_int rightLine) "." (format_int rightCol) ":"
             message
           >>
        | _ => (!SMLFormat.BasicFormatters.format_exn_Ref) x
    val _ = SMLFormat.BasicFormatters.format_exn_Ref := format
  in end

format_exn_Refformat_exńABasicFormattersXgN`ɂ̂悤ɒ`ĂB

  val format_exn_Ref =
      ref
      (fn exn => 
          let val text = General.exnMessage exn
          in [FE.Term (size text, text)] end)

  fun format_exn exn = !format_exn_Ref exn

: ݂SMLFormat̎́AO錾ɑ΂tH[}b^ɂāAȉ̓_ɊւĐ݂ĂB
1, q"prefix"^OO錾ɑ΂ĎwłȂB
2, ̌`̗O`ɑ΂ătH[}bgRgw肷邱Ƃ͂łȂB
     exception E1 = E2

====================
4.12. prefix^O

prefix^OpƁAЂƂtype/datatype錾ɑ΂ĕ̃tH[}b^邱ƂłB
prefix^O͕p[^ɎB̃p[^͐tH[}b^̖ÕvtBNXƂĎgpB

  (*%
   * @prefix summary
   *)
  (*%
   * @prefix detail
   *)
  type address =
                (*%
                 * @prefix summary
                 * @format({zip, state, city}) state
                 *)
                (*%
                 * @prefix detail
                 * @format({zip, state, city})
                 *   "zip=" zip ",state=" state ",city=" city
                 *)
                {zip : string, state : string, city : string}

addressɑ΂āA̓̃tH[}b^B

  fun summaryaddress x =
      case x of
        {zip, state, city} => << format_string state >>

  fun detailaddress x =
      case x of
        {zip, state, city} =>
          <<
            "zip=" (format_string zip)
            ",state=" (format_string state)
            ",city=" (format_string city)
          >>

prefix^O͖OԂw肷ӖB
tH[}b^́AvtBNXw肳ꂽtH[}bgRg琶ꂽtH[}b^݂̂ĂяoƂłB
iOƂāAformat_stringformat_intȂBasicFormattersŐ錾ĂtH[}b^͂̃tH[}b^ĂяoƂłBj

  (*%
   * @prefix detail
   *)
  type customer = 
                  (*%
                   * @prefix detail
                   * @prefix({name, address, tel})
                   *      "name=" name ",address=" address ",tel=" tel
                   *)
                  {name : string, address : address, tel : string}

ȉ̂悤ɁAcustomerɑ΂ĐtH[}b^́Aaddressɑ΂ĐꂽtH[}b^̂AprefixdetailƂtH[}b^ŌĂяoB

  fun detailcustomer x =
      case x of
        {name, address, tel} =>
          <<
            "name=" (format_string name)
            ",address=" (detailaddress address)
            ",tel=" (format_string tel)
          >>

قȂprefixw肳ꂽtH[}b^Ăяoɂ́Aformatter^OgpB

prefix^Ow肳ĂȂꍇ́A"format_"vtBNXɎw肳ꂽ̂Ƃ݂ȂB

datatypeɂĂlprefix^Opĕ̃tH[}b^𐶐łB

  (*%
   * @prefix formatPlain
   *)
  (*%
   * @prefix formatHTML
   *)
  datatype block = 
                  (*%
                   * @prefix formatPlain
                   * @format(text) text
                   *)
                  (*%
                   * @prefix formatHTML
                   * @format(text) text
                   *)
                  Text of string
                |
                  (*%
                   * @prefix formatPlain
                   * @format(block) block
                   *)
                  (*%
                   * @prefix formatHTML
                   * @format(block) "<B>" block "</B>"
                   *)
                   Bold of block

̃tH[}b^B

  fun formatPlainblock x =
      case x of
        Text text => << format_string text >>
      | Bold block => << formatPlainblock block >>

  fun formatHTMLblock x =
      case x of
        Text text => << format_string text >>
      | Bold block => << "<B>" formatHTMLblock block "</B>" >>


========================================
