I sometimes want to compare FriCAS output with that what Mathematica returns and also wanted to be able to cut&paste FriCAS expressions to Mathematica without always having the need to change the syntax manually. I therefore modified Format1D in such a way that it shows Mathematica syntax.

Of course, that cannot be perfect, because OutputForm is an output format and does not contain enough information. Nevertheless, the attached file produces Mathematica expressions for many common cases.

Please try your favourite expression(s) and let me know where I should adapt something.

Use as follows:

)compile fmtmma.spad
strmma x ==> first(lines(format(format(x::OutputForm)$Formatter(FormatMathematica))))
dispmma x ==> display(x::OutputForm::Formatter(FormatMathematica))

strmma(sin(x)^(a+tan(x^(-1))))
dispmma(sin(x)^(a+tan(x^(-1))))
dispmma(sum(sin(k*x),k=1..n))

===============================
%%% (33) -> strmma(sin(x)^(a+tan(x^(-1))))

   (33)  "Sin[x]^(Tan[1/x]+a)"
                                                Type: String
%%% (34) -> dispmma(sin(x)^(a+tan(x^(-1))))
Sin[x]^(Tan[1/x]+a)
                                                Type: Void
%%% (35) -> dispmma(sum(sin(k*x),k=1..n))
   [OUTPUTFORM = k = 1, SEXPRESSION = (= k 1)]
Sum[Sin[k*x], {k, 1, n}]
                                                Type: Void

Ralf

--
You received this message because you are subscribed to the Google Groups "FriCAS - 
computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to fricas-devel+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/fricas-devel/81040453-ba21-463d-aa48-7b871ee676ef%40hemmecke.org.
-------------------------------------------------------------------
---
--- FriCAS FormatMathematica
--- Copyright (C) 2025  Ralf Hemmecke <r...@hemmecke.org>
---
-------------------------------------------------------------------
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
--
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials provided
-- with the distribution.
--
-- 3. Neither the name of the copyright holder nor the names of its
-- contributors may be used to endorse or promote products derived
-- from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-- OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
-- This program first computes a data structure that represents the
-- documentation of all constructors and the documentation of their
-- signatures in raw (SExpression).
-- In the following pass, the ++ docstrings are embellished by
-- transforming (known) constructor names into links.
-- Finally, the data structure will be output into a collection of
-- .rst files that can be processed by sphinx.
-------------------------------------------------------------------
)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass{article}
\usepackage{literatedoc}
\begin{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{FormatMathematica---A formatter for Mathematica}
\author{Ralf Hemmecke}
\date{12-Mar-2025}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\maketitle

\begin{abstract}
  The domain \spadtype{FormatMathematica} provides functionality to
  transform an element of \spadtype{OutputForm} into a linear
  (one-dimensional) form with the aim that it can be used directly via
  cut\&paste as input to Mathematica.
\end{abstract}

\tableofcontents

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Overview}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

For an overview of the formatting framework in \SYSTEM{} look into the
\url{fmt.spad} document.

The domain \spadtype{FormatMathematica} try to output an expression in
a form that can be pasted into a Mathematica session. Since
\spadtype{OutputForm} does not necessarily provide all information to
reproduce the original expression this domain can only be considered
as an approximation to a true Mathematica expression. It will
certainly work in the most common cases, but are cases where the
output cannot be read properly by Mathematica.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{The Implementation of \spadtype{FormatMathematica}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif


)abbrev domain FMTMMA FormatMathematica
++ \spadtype{FormatMMA} provides a coercion from \spadtype{OutputForm}
++ to a one-dimensional format such that the output can be pasted back
++ as input into a Mathematica session.
FormatMathematica: Exports == Implementation where
  E   ==> OutputForm
  Z   ==> Integer
  N   ==> NonNegativeInteger
  S   ==> String
  LE  ==> List E
  BOX ==> OutputBox
  LBOX ==> S -> BOX -- Label box for prologue and epilogue
  HANDLER ==> (Z, LE) -> OutputBox -- (precedence, arguments) +-> resulting box
  H ==> HANDLER

  Exports ==> FormatterCategory

  Implementation ==> add
    Rep ==> Record(prolog: BOX, fmt: BOX, epilog: BOX)
    ProEpi ==> Record(prolog: LBOX, epilog: LBOX)
    import from Rep
    rep x ==> (x@%) pretend Rep
    per x ==> (x@Rep) pretend %

    FE ==> formatExpression
    MIN ==> minPrecedence()
    MAX ==> maxPrecedence()

    coerce(x: %): OutputForm == rep(x)::OutputForm

)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
By default there is no prologue or epilogue for one-dimensional output.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

    defaultPrologue(label: S): BOX == empty()
    defaultEpilogue(label: S): BOX == empty()

)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\spad{fricasEscapeString(s)} escapes all Mathamatica special characters.
These characters are: \verb|" \|. %"

We also escape these characters by the Mathematica escape character,
i.e., a backslash character.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

    -- local function: fricasEscapeString
    fricasEscapeString(s: S): S == -- local function
        cc: CharacterClass := charClass "_"\"
        p: Integer := position(cc, s, 1)
        zero? p => s
        str: S := ""
        n: Integer := 1
        while (p := position(cc, s, n)) > 0 repeat
            str := concat(str, s(n..p-1))
            n := p+1
            esc := concat("\", s.p)
            str := concat(str, esc)
        concat(str, s(n..#s))

    formatFunction(b: BOX, lb: List BOX): BOX ==
        import from OutputFormTools
        empty? lb => hconcat [b, parenthesize("[", "]", empty()$BOX)]
        bx: BOX := first lb
        for x in rest lb repeat bx := hconcat [bx, box ", ", x]
        hconcat [b, parenthesize("[", "]", bx)]

    function(op: S, p: Z, hh: H): H == prefix(op, p, bracket("[", "]", hh))

    -- Take category default for formatInteger
    formatFloat(s: S): BOX == box remove(char "__", s)
    formatString(s: S): BOX ==
        import from E
        s = "true"  => box "True"
        s = "false" => box "False"
        #s>1 and s.1 = char "_"" and s(#s) = char "_"" =>
            parenthesize("_"", "_"", box fricasEscapeString s(2..#s-1))
        box fricasEscapeString s
    formatSymbol(s: S): BOX == box s
    formatFunctionSymbol(s: S): BOX == box s

    -- Functions from FormatterCategory
    parenthesize(left: S, right: S, b: BOX): BOX ==
        hconcat [box left, b, box right]

    -- Replace x by y in expression z.
    substitute(x: E, y: E, z: E): E ==
        import from OutputFormTools
        x = z => y
        atom? z => z
        args: List E := [substitute(x, y, a) for a in arguments z]
        elt(substitute(x, y, operator z), args)

    -- From e=(* a (CONCAT d x)) return x and empty() in case the form
    -- does not have this structure.
    getDExpression(e: E): E ==
        import from OutputFormTools
        atom? e => empty()
        op: E := operator e
        not is_symbol?(op, "*"::Symbol) => empty()
        args: LE := arguments e
        #args ~= 2 => empty()
        op2: E := operator(args.2)
        not is_symbol?(op2, "CONCAT"::Symbol) => empty()
        args2: LE := arguments(args.2)
        #args2 ~= 2 or not is_symbol?(first args2, "d"::Symbol) => empty()
        args2.2

    -- Check documentation in fmtcat.spad for the different cases.
    integral(p: Z): H == (prec: Z, args: LE): BOX +->
        -- We can assume #args=3.
        bl: BOX := formatExpression(args.1, MIN) -- lower limit
        bu: BOX := formatExpression(args.2, MIN) -- upper limit
        empty? bu =>
            lb: List BOX := [formatExpression(args.3, MIN)]
            if not empty? bl then lb := concat(lb, bl)
            return formatFunction(box "Integrate", lb)

        --assert(not empty? bu)
        b2: BOX := bu
        x: E := getDExpression(args.3)
        ba: BOX := formatExpression(args.3, MIN) -- default without substitution
        if x ~= empty() then -- must replace in args.3
             -- Here, the expression a=args.3 is of the form
             -- (* a (CONCAT d x)). We substitute any x in a by
             -- the upper limit and return this expression without
             -- the (CONCAT d x) part.
            bx: BOX := formatExpression(x, MIN)
            -- remove (CONXAT d x) part
            a: E := first arguments(args.3)$OutputFormTools
            if empty? bl then -- must substitute
                ba := formatExpression(substitute(x, args.2, a), MIN)
              else -- no substitution necessary
                -- limits are given by x=bl..bu
                ba := formatExpression(a, MIN)
                b2 := hconcat [box "{", bx, box ", ", bl, box ", ", bu, box "}"]
        formatFunction(box "Integrate", [ba, b2])

    -- local
    operatorWithLimits(s: S, p: Z): H == (prec: Z, args: LE): BOX +->
        -- We can assume #args>=2, but the first argument can be empty
        bl: BOX := formatExpression(args.1, MIN) -- lower limit
        ba: BOX := formatExpression(args.2, MIN) -- upper limit or arg
        #args = 2 =>
            empty? bl => formatFunction(box s, [ba])
            formatFunction(box s, [ba, bl])
        bu: BOX := ba -- upper limit
        ba := formatExpression(args.3, MIN) -- arg (no parens needed)
        -- Normally, lower limit looks like (= var val)
        import from OutputFormTools
        atom?(args.1) or not symbol?(op:=operator args.1) or
          symbol(op) ~= "="::Symbol =>
            b2: BOX := hconcat [box "{", bl, box ", ", bu, box "}"]
        as: LE := arguments(args.1)
        bv: BOX := formatExpression(as.1, MIN)
        bl: BOX := formatExpression(as.2, MIN)
        b2 := hconcat [box "{", bv, box ", ", bl, box ", ", bu, box "}"]
        formatFunction(box s, [ba, b2])

    sum(p: Z): H == operatorWithLimits("Sum", p)
    product(p: Z): H == operatorWithLimits("Product", p)

    theMap(prec: Z, args: LE): BOX ==
        import from OutputFormTools
        a: E := first args
        s: S :=
            atom? a and not string? a and not symbol? a => ";?;"
            b: BOX := formatExpression(a, MIN) -- assume only one line!!!
            first lines b -- strings are already run through texEscape
        p1 := position(char ";", s)
        p2 := position(char ";", s, p1+1)
        parenthesize("theMap[", "]", box s(p1+1..p2-1))

    overbar(p: Z, hh: H): H == (prec: Z, args: LE): BOX +->
        formatFunction(box "OverBar", [hh(p, args)])

    box(hh: H): H == (prec: Z, args: LE): BOX +->
        formatFunction(box "Framed", [hh(prec, [args.1])])

    -- \sqrt[n]{x}
    nthRoot(p: Z, h1: H, h2: H): H == (prec: Z, args: LE): BOX +->
        bx: BOX := h1(p, [args.1])
        one?(# args) => formatFunction(box "Sqrt", [bx])
        b2: BOX := formatFunction(box "Power", [h2(p, [args.2]),box "-1"])
        formatFunction(box "Power", [bx, b2])

    emptyArgument?(a: E): Boolean ==
        import from OutputFormTools
        atom? a => string? a and (string a = " " or string a = "")
        is_symbol?(operator a, "NOTHING"::Symbol)

    formatMaybeEmptyExpression(a: E): BOX ==
        emptyArgument? a => box "_"_""
        formatExpression(a, MIN)

    scripts(p: Z): H == (prec: Z, args: LE): BOX +->
        lb: List BOX := [formatMaybeEmptyExpression a for a in args]
        empty? rest args => first lb
        -- gives wrong expressionn if #lb>2
        formatFunction(box "Subsuperscript", lb)

    subscript(p: Z): H == (prec: Z, args: LE): BOX +->
        b1: BOX := formatExpression(args.1, MIN)
        b2: BOX := formatExpression(args.2, MIN)
        formatFunction(box "Subscript", [b1, b2])


)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The handler \spad{altsupersub} treats an expression that is generated by
\begin{verbcode}
supersub(a, [sub1, super1, sub2, super2, ...])
supersub(a, [l1, u1, l2, u2, ...])
\end{verbcode}
from \spadtype{OutputForm}. We basically turn it from its
representation in \spadtype{OutputForm} back into the above form.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

    altsupersub(p: Z): H == (prec: Z, args: LE): BOX +->
        lb: List BOX := [formatMaybeEmptyExpression a for a in args]
        n: N := #args
        one? n => first lb
        if even? n then lb := concat(lb, box "_"_"")
        formatFunction(box "Subsuperscript", lb)

    -- we must treat the special format of a prime expression
    prime(p: Z): H == (prec: Z, args: LE): BOX +->
        b1: BOX := formatExpression(args.1, MIN)
        n: Z := numberOfPrimes(args.2)
        n < 0 => error "error in PRIME expression"
        b2: BOX := box(convert(n)@String)
        formatFunction(formatFunction(box "Derivative", [b2]), [b1])

    power(p: Z, h1: H, h2: H): H == (prec: Z, args: LE): BOX +->
        b1: BOX := h1(p+1, [args.1])
        b2: BOX := h2(p+1, [args.2])
        parenthesizeIf(p < prec, hconcat [b1, box "^", b2])

    fraction(p: Z, h1: H, h2: H): H ==  (prec: Z, args: LE): BOX +->
        b1: BOX := h1(p+1, [args.1])
        b2: BOX := h2(p+1, [args.2])
        parenthesizeIf(p < prec, hconcat [b1, box "/", b2])

    slash(p: Z, h1: H, h2: H): H == fraction(p, h1, h2)

    binomial(prec: Z, args: LE): BOX ==
        b1: BOX := formatExpression(args.1, MIN)
        b2: BOX := formatExpression(args.2, MIN)
        formatFunction(box "Binomial", [b1, b2])

    zag(prec: Z, args: LE): BOX ==
        b1: BOX := formatExpression(args.1, MIN)
        b2: BOX := formatExpression(args.2, MIN)
        formatFunction(box "zag", [b1, b2])

    vconcat(h: H): H == bracket("vconcat[", "]", nary(", ", MAX, FE MIN))
    pile(h: H): H == bracket("pile[", "]", nary(", ", MAX, FE MIN))

    matrix(left: S, right: S): H == (prec: Z, args: LE): BOX +->
        entries: BOX := nary(", ", MAX, FE MIN)(prec, rest args)
        parenthesize(left, right, entries)

)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Now all function are defined and we can fill the \spad{oh}
data structure.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

    setOperatorHandlers!(oh: OperatorHandlers H): OperatorHandlers H ==
        NARY ==> -1 -- means n-ary.
        PAREN p ==> bracket("(", ")", FE p)
        PAREN2(p1, p2) ==> bracket("(", ")", infix(", ", MAX, FE MIN, FE MIN))
        FUNCTION s ==> function(s, MAX, FE MIN)

        o(n, op, hdl) ==> setHandler!(oh, n, op, hdl)

        o(0, "NOTHING",     nothing())
        o(0, "%pi",         formatConstant "Pi")
        o(0, "%e",          formatConstant "E")
        o(0, "%i",          formatConstant "I")
        o(0, "true",        formatConstant "True")
        o(0, "false",       formatConstant "False")

)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Note that we would need more effort to rediscover \verb|%plusInfinity|
and \verb|%minusInfinity| from the \spadtype{OutputForm}
representation.
\begin{verbcode}
(82) -> e %plusInfinity
   [OUTPUTFORM =  + infinity, SEXPRESSION = (+ (NOTHING) infinity)]

(83) -> e %minusInfinity
   [OUTPUTFORM = - infinity, SEXPRESSION = (- infinity)]

(84) -> e %Infinity
   [OUTPUTFORM = %Infinity, SEXPRESSION = %Infinity]
\end{verbcode}

Here we (wrongly) return \verb|+%Infinity| and \verb|-%Infinity| for
\verb|%plusInfinity| and \verb|%minusInfinity|.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

        o(0, "%Infinity",   formatConstant "Infinity")
        o(0, "infinity",    formatConstant "Infinity") -- for %minusInfinity

        o(0, "...",         formatConstant "...")

        o(1, "cos",         FUNCTION "Cos")
        o(1, "cot",         FUNCTION "Cot")
        o(1, "csc",         FUNCTION "Csc")
        o(1, "log",         FUNCTION "Log")
        o(1, "sec",         FUNCTION "Sec")
        o(1, "sin",         FUNCTION "Sin")
        o(1, "tan",         FUNCTION "Tan")
        o(1, "cosh",        FUNCTION "Cosh")
        o(1, "coth",        FUNCTION "Coth")
        o(1, "csch",        FUNCTION "Csch")
        o(1, "sech",        FUNCTION "Sech")
        o(1, "sinh",        FUNCTION "Sinh")
        o(1, "tanh",        FUNCTION "Tanh")
        o(1, "acos",        FUNCTION "ArcCos")
        o(1, "asin",        FUNCTION "ArcSin")
        o(1, "atan",        FUNCTION "ArcTan")
        o(1, "erf",         FUNCTION "Erf")
        o(1, "Gamma",       FUNCTION "Gamma")

        o(1, "-",           prefix("-",      710, FE 715))
        o(1, "not",         FUNCTION "Not")

        o(1, "QUOTE",       FUNCTION "HoldFormComplete")
        o(1, "OVERBAR",     overbar(MAX, FE MIN))
        o(1, "BOX",         box FE MIN)
        o(1, "Aleph",       FUNCTION "\[Aleph]")
        o(1, "BRACE",       bracket("{", "}", FE MIN)) -- set as list
        o(1, "BRACKET",     bracket("{", "}", FE MIN)) -- Mathematica lists
        o(1, "PAREN",       bracket("(", ")", FE MIN))
        o(1, "ROOT",        FUNCTION "Sqrt")
        o(1, "SEGMENT",     bracket("", " .. ", FE 990))
        o(1, "STRING",      bracket("_"", "_"", FE MIN))

        o(2, "rem",         function("Mod",      MAX, nary(", ",MAX,FE MIN)))
        o(2, "quo",         function("Quotient", MAX, nary(", ",MAX,FE MIN)))
        o(2, "exquo",       function("Quotient", MAX, nary(", ",MAX,FE MIN)))

        o(2, "^",           power(950, FE 960, FE 960))
        o(2, "/",           fraction(910, FE 910, FE 910))
        o(2, "OVER",        fraction(910, FE 910, FE 910))
        o(2, "SLASH",       slash(910, FE 910, FE 910))
        o(2, "ZAG",         zag)
        o(2, "BINOMIAL",    binomial)
        o(2, "PRIME",       prime MAX)

        o(2, "ROOT",        nthRoot(970, FE MIN, FE MIN))
        o(2, "SUB",         subscript 950)

        o(2, "SEGMENT",     infix(" .. ",        100, FE 100, FE 100))

        o(2, "TENSOR",      prefix("tensor",     MAX, PAREN2(MIN, MIN)))

        o(2, "EQUATNUM",    prefix("\EQUATNUM",  MAX, PAREN2(MIN, MIN)))
        o(2, "OVERLABEL",   prefix("\OVERLABEL", MAX, PAREN2(MIN, MIN)))

        o(2, "==",          nary("==",         400, FE 401))

        o(2, "=",           nary("==",         400, FE 400))
        o(2, "~=",          nary("!= ",        400, FE 400))
        o(2, "<",           nary("<",          400, FE 400))
        o(2, ">",           nary(">",          400, FE 400))
        o(2, "<=",          nary("<=",         400, FE 400))
        o(2, ">=",          nary(">=",         400, FE 400))
        o(2, "and",         nary(" && ",       300, FE 300))
        o(2, "or",          nary(" || ",       200, FE 200))
        o(2, "LET",         nary("=",          125, FE 125))
        o(2, "->",          nary("->",         1001, FE 1001))
        o(2, "~>",          nary("->",         100, FE 100))
        o(2, "+->",         function( "FUNCTION", MAX, nary(", ",MAX,FE MIN)))
        o(2, "|",           nary(" | ",        100, FE 100))

        o(2, "SIGMA",       sum 750)
        o(2, "PI",          product 750)

        o(3, "SIGMA2",      sum 750)
        o(3, "PI2",         product 750)
        o(3, "INTSIGN",     integral 700)

        o(NARY, "+",           naryPlus("+", "-",  700, FE 700))
        -- Does n-ary minus ever appear in OutputForm???
        o(NARY, "-",           naryPlus("+", "-",  700, FE 700))

        o(NARY, "*",           nary("*",           800, FE 800))

        o(NARY, "AGGLST",      nary(", ",          MAX, FE MIN))
        o(NARY, "AGGSET",      nary("; ",          MAX, FE MIN))
        o(NARY, "CONCAT",      nary("",            MAX, FE MIN))
        o(NARY, "CONCATB",     nary(" ",           MAX, FE MIN))

        o(NARY, "ALTSUPERSUB", altsupersub 900)
        o(NARY, "SUPERSUB",    scripts 900)
        o(NARY, "SC",          pile FE MIN) -- pile notation
        o(NARY, "VCONCAT",     vconcat FE MIN)

        o(NARY, "ROW",         bracket("{", "}", nary(", ", MAX, FE MIN)))
        o(NARY, "MATRIX",      matrix("{", "}"))
        o(NARY, "theMap",      theMap) -- one or two arguments

        return oh

    -- local variable declarations and definitions
    operatorData: OperatorHandlers(H) := setOperatorHandlers! new()
    operatorHandlers(): OperatorHandlers(HANDLER) == operatorData

)if LiterateDoc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
)endif

Reply via email to