diff --git a/mathics/builtin/box/layout.py b/mathics/builtin/box/layout.py
index 680215b27..079f84551 100644
--- a/mathics/builtin/box/layout.py
+++ b/mathics/builtin/box/layout.py
@@ -188,6 +188,33 @@ def eval_display(boxexpr, evaluation):
         return boxexpr.elements[0]
 
 
+class PaneBox(BoxExpression):
+    """
+    <url>
+    :WMA link:
+    https://reference.wolfram.com/language/ref/InterpretationBox.html</url>
+
+    <dl>
+      <dt>'PaneBox[expr]'
+      <dd> is a low-level box construct, used in OutputForm.
+    </dl>
+
+    """
+
+    attributes = A_HOLD_ALL_COMPLETE | A_PROTECTED | A_READ_PROTECTED
+    summary_text = "box associated to panel"
+
+    def apply_display_form(boxexpr, form, evaluation, expression):
+        """ToExpression[boxexpr_PaneBox, form_]"""
+        return Expression(expression.head, boxexpr.elements[0], form).evaluate(
+            evaluation
+        )
+
+    def apply_display(boxexpr, evaluation):
+        """DisplayForm[boxexpr_PaneBox]"""
+        return boxexpr.elements[0]
+
+
 class RowBox(BoxExpression):
     """
     <url>
diff --git a/mathics/builtin/forms/output.py b/mathics/builtin/forms/output.py
index a01bb046f..d48e98e45 100644
--- a/mathics/builtin/forms/output.py
+++ b/mathics/builtin/forms/output.py
@@ -37,6 +37,7 @@
     StringLParen,
     StringRParen,
     eval_baseform,
+    eval_makeboxes_outputform,
     eval_mathmlform,
     eval_tableform,
     eval_texform,
@@ -490,8 +491,13 @@ class OutputForm(FormBaseClass):
      = -Graphics-
     """
 
+    formats = {"OutputForm[s_String]": "s"}
     summary_text = "plain-text output format"
 
+    def eval_makeboxes(self, expr, form, evaluation):
+        """MakeBoxes[OutputForm[expr_], form_]"""
+        return eval_makeboxes_outputform(expr, evaluation, form)
+
 
 class PythonForm(FormBaseClass):
     """
diff --git a/mathics/core/atoms.py b/mathics/core/atoms.py
index d6e542a60..e2b37e4c9 100644
--- a/mathics/core/atoms.py
+++ b/mathics/core/atoms.py
@@ -1016,10 +1016,13 @@ def __str__(self) -> str:
         return '"%s"' % self.value
 
     def atom_to_boxes(self, f, evaluation):
+        return self.make_boxes(f.get_name())
+
+    def make_boxes(self, f):
         from mathics.eval.makeboxes import _boxed_string
 
         inner = str(self.value)
-        if f in SYSTEM_SYMBOLS_INPUT_OR_FULL_FORM:
+        if f in ("System`InputForm", "System`FullForm"):
             inner = '"' + inner.replace("\\", "\\\\") + '"'
             return _boxed_string(inner, **{"System`ShowStringCharacters": SymbolTrue})
         return String('"' + inner + '"')
diff --git a/mathics/eval/makeboxes/__init__.py b/mathics/eval/makeboxes/__init__.py
index a6cb2a6e7..ec20abf22 100644
--- a/mathics/eval/makeboxes/__init__.py
+++ b/mathics/eval/makeboxes/__init__.py
@@ -7,6 +7,7 @@
     _boxed_string,
     eval_generic_makeboxes,
     eval_makeboxes,
+    eval_makeboxes_outputform,
     format_element,
     int_to_string_shorter_repr,
     to_boxes,
@@ -18,7 +19,11 @@
     eval_tableform,
     eval_texform,
 )
-from mathics.eval.makeboxes.precedence import builtins_precedence, parenthesize
+from mathics.eval.makeboxes.precedence import (
+    builtins_precedence,
+    compare_precedence,
+    parenthesize,
+)
 
 __all__ = [
     "NumberForm_to_String",
@@ -26,11 +31,13 @@
     "StringRParen",
     "_boxed_string",
     "builtins_precedence",
+    "compare_precedence",
     "do_format",
     "eval_baseform",
     "eval_generic_makeboxes",
     "eval_infix",
     "eval_makeboxes",
+    "eval_makeboxes_outputform",
     "eval_mathmlform",
     "eval_postprefix",
     "eval_tableform",
diff --git a/mathics/eval/makeboxes/makeboxes.py b/mathics/eval/makeboxes/makeboxes.py
index 2d7275a2e..66b8c6b4d 100644
--- a/mathics/eval/makeboxes/makeboxes.py
+++ b/mathics/eval/makeboxes/makeboxes.py
@@ -13,7 +13,7 @@
 from mathics.core.evaluation import Evaluation
 from mathics.core.expression import Expression
 from mathics.core.symbols import Atom, Symbol, SymbolFullForm, SymbolMakeBoxes
-from mathics.core.systemsymbols import SymbolStandardForm
+from mathics.core.systemsymbols import SymbolOutputForm, SymbolStandardForm
 from mathics.eval.makeboxes.formatvalues import do_format
 from mathics.eval.makeboxes.precedence import parenthesize
 
@@ -126,8 +126,21 @@ def int_to_string_shorter_repr(value: int, form: Symbol, max_digits=640):
     return String(value_str)
 
 
+def eval_makeboxes_outputform(expr, evaluation, form):
+    """
+    Build a 2D text representation of the expression.
+    """
+    from mathics.builtin.box.layout import InterpretationBox, PaneBox
+    from mathics.format.outputform import expression_to_outputform_text
+
+    text_outputform = str(expression_to_outputform_text(expr, evaluation, form))
+    elem1 = PaneBox(String(text_outputform))
+    elem2 = Expression(SymbolOutputForm, expr)
+    return InterpretationBox(elem1, elem2)
+
+
 def eval_fullform_makeboxes(
-    self, expr, evaluation: Evaluation, form=SymbolStandardForm
+    expr, evaluation: Evaluation, form=SymbolStandardForm
 ) -> Optional[BaseElement]:
     """
     This function takes the definitions provided by the evaluation
@@ -220,9 +233,27 @@ def format_element(
     Applies formats associated to the expression, and then calls Makeboxes
     """
     evaluation.is_boxing = True
+    while element.get_head() is form:
+        element = element.elements[0]
+
+    if element.has_form("FullForm", 1):
+        return eval_fullform_makeboxes(element.elements[0], evaluation)
+
+    # In order to work like in WMA, `format_element`
+    # should evaluate `MakeBoxes[element//form, StandardForm]`
+    # Then, MakeBoxes[expr_, StandardForm], for any expr,
+    # should apply Format[...] rules, and then
+    # MakeBoxes[...] rules. These rules should be stored
+    # as FormatValues[...]
+    # As a first step in that direction, let's mimic this behaviour
+    # just for the case of OutputForm:
+    if element.has_form("OutputForm", 1):
+        return eval_makeboxes_outputform(element.elements[0], evaluation, form)
+
     expr = do_format(element, evaluation, form)
     if expr is None:
         return None
+
     result = Expression(SymbolMakeBoxes, expr, form)
     result_box = result.evaluate(evaluation)
     if isinstance(result_box, String):
diff --git a/mathics/format/latex.py b/mathics/format/latex.py
index 36cf65917..31fc5209d 100644
--- a/mathics/format/latex.py
+++ b/mathics/format/latex.py
@@ -19,6 +19,8 @@
 from mathics.builtin.box.layout import (
     FractionBox,
     GridBox,
+    InterpretationBox,
+    PaneBox,
     RowBox,
     SqrtBox,
     StyleBox,
@@ -133,6 +135,16 @@ def render(format, string, in_text=False):
 add_conversion_fn(String, string)
 
 
+def interpretation_panebox(self, **options):
+    return lookup_conversion_method(self.elements[0], "latex")(
+        self.elements[0], **options
+    )
+
+
+add_conversion_fn(InterpretationBox, interpretation_panebox)
+add_conversion_fn(PaneBox, interpretation_panebox)
+
+
 def fractionbox(self, **options) -> str:
     _options = self.box_options.copy()
     _options.update(options)
diff --git a/mathics/format/mathml.py b/mathics/format/mathml.py
index 7bbdd65da..d8ac94922 100644
--- a/mathics/format/mathml.py
+++ b/mathics/format/mathml.py
@@ -15,6 +15,8 @@
 from mathics.builtin.box.layout import (
     FractionBox,
     GridBox,
+    InterpretationBox,
+    PaneBox,
     RowBox,
     SqrtBox,
     StyleBox,
@@ -110,6 +112,16 @@ def render(format, string):
 add_conversion_fn(String, string)
 
 
+def interpretation_panebox(self, **options):
+    return lookup_conversion_method(self.elements[0], "latex")(
+        self.elements[0], **options
+    )
+
+
+add_conversion_fn(InterpretationBox, interpretation_panebox)
+add_conversion_fn(PaneBox, interpretation_panebox)
+
+
 def fractionbox(self, **options) -> str:
     _options = self.box_options.copy()
     _options.update(options)
diff --git a/mathics/format/outputform.py b/mathics/format/outputform.py
new file mode 100644
index 000000000..0fc8309ec
--- /dev/null
+++ b/mathics/format/outputform.py
@@ -0,0 +1,779 @@
+"""
+This module builts the 2D string associated to the OutputForm
+"""
+
+from typing import Callable, Dict, List, Union
+
+from mathics.core.atoms import (
+    Integer,
+    Integer1,
+    Integer2,
+    IntegerM1,
+    Rational,
+    Real,
+    String,
+)
+from mathics.core.element import BaseElement
+from mathics.core.evaluation import Evaluation
+from mathics.core.expression import Expression
+from mathics.core.list import ListExpression
+from mathics.core.symbols import Atom, Symbol, SymbolTimes
+from mathics.core.systemsymbols import (
+    SymbolDerivative,
+    SymbolInfix,
+    SymbolNone,
+    SymbolOutputForm,
+    SymbolPower,
+    SymbolStandardForm,
+    SymbolTraditionalForm,
+)
+from mathics.eval.makeboxes import compare_precedence, do_format  # , format_element
+
+SymbolNonAssociative = Symbol("System`NonAssociative")
+SymbolPostfix = Symbol("System`Postfix")
+SymbolPrefix = Symbol("System`Prefix")
+SymbolRight = Symbol("System`Right")
+SymbolLeft = Symbol("System`Left")
+
+
+expr_to_outputform_text_map: Dict[str, Callable] = {}
+
+
+# This Exception if the expression should
+# be processed by the default routine
+class _WrongFormattedExpression(Exception):
+    pass
+
+
+class IsNotGrid(Exception):
+    pass
+
+
+class IsNot2DArray(Exception):
+    pass
+
+
+def parenthesize(expr_str: str) -> str:
+    """wrap with parenthesis"""
+    return f"({expr_str})"
+
+
+def bracket(expr_str: str) -> str:
+    """wrap with square brackets"""
+    return f"[{expr_str}]"
+
+
+def grid(expr):
+    raise NotImplementedError
+
+
+def expression_to_outputform_text(
+    expr: BaseElement, evaluation: Evaluation, form=SymbolStandardForm, **kwargs
+):
+    """
+    Build a 2d text from an `Expression`
+    """
+    ## TODO: format the expression
+    format_expr: Expression = do_format(expr, evaluation, SymbolOutputForm)  # type: ignore
+
+    # Strip HoldForm
+    while format_expr.has_form("HoldForm", 1):  # type: ignore
+        format_expr = format_expr.elements[0]
+
+    lookup_name = format_expr.get_head().get_lookup_name()
+    try:
+        result = expr_to_outputform_text_map[lookup_name](
+            format_expr, evaluation, form, **kwargs
+        )
+        return result
+    except _WrongFormattedExpression:
+        # If the key is not present, or the execution fails for any reason, use
+        # the default
+        pass
+    except KeyError:
+        pass
+    return _default_expression_to_outputform_text(
+        format_expr, evaluation, form, **kwargs
+    )
+
+
+def _default_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    """
+    Default representation of a function
+    """
+    expr_head = expr.head
+    head = expression_to_outputform_text(expr_head, evaluation, form, **kwargs)
+    comma = ", "
+    elements = [
+        expression_to_outputform_text(elem, evaluation) for elem in expr.elements
+    ]
+    result = elements.pop(0) if elements else " "
+    while elements:
+        result = result + comma + elements.pop(0)
+
+    if form is SymbolTraditionalForm:
+        return head + parenthesize(result)
+    return head + bracket(result)
+
+
+def _divide(num, den, evaluation, form, **kwargs):
+    infix_form = Expression(
+        SymbolInfix, ListExpression(num, den), String("/"), Integer(400), SymbolLeft
+    )
+    return expression_to_outputform_text(infix_form, evaluation, form, **kwargs)
+
+
+def _strip_1_parm_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    if len(expr.elements) != 1:
+        raise _WrongFormattedExpression
+    return expression_to_outputform_text(expr.elements[0], evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map[
+    "System`HoldForm"
+] = _strip_1_parm_expression_to_outputform_text
+expr_to_outputform_text_map[
+    "System`InputForm"
+] = _strip_1_parm_expression_to_outputform_text
+
+
+def derivative_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    """Derivative operator"""
+    head = expr.get_head()
+    if head is SymbolDerivative:
+        return _default_expression_to_outputform_text(expr, evaluation, form, **kwargs)
+    super_head = head.get_head()
+    if super_head is SymbolDerivative:
+        expr_elements = expr.elements
+        if len(expr_elements) != 1:
+            return _default_expression_to_outputform_text(
+                expr, evaluation, form, **kwargs
+            )
+        function_head = expression_to_outputform_text(
+            expr_elements[0], evaluation, form, **kwargs
+        )
+        derivatives = head.elements
+        if len(derivatives) == 1:
+            order_iv = derivatives[0]
+            if order_iv == Integer1:
+                return function_head + "'"
+            elif order_iv == Integer2:
+                return function_head + "''"
+
+        return _default_expression_to_outputform_text(expr, evaluation, form, **kwargs)
+
+    # Full Function with arguments: delegate to the default conversion.
+    # It will call us again with the head
+    return _default_expression_to_outputform_text(expr, evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map[
+    "System`Derivative"
+] = derivative_expression_to_outputform_text
+
+
+def divide_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    if len(expr.elements) != 2:
+        raise _WrongFormattedExpression
+    num, den = expr.elements
+    return _divide(num, den, evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map["System`Divide"] = divide_expression_to_outputform_text
+
+
+def graphics(expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs) -> str:
+    return "-Graphics-"
+
+
+expr_to_outputform_text_map["System`Graphics"] = graphics
+
+
+def graphics3d(expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs) -> str:
+    return "-Graphics3D-"
+
+
+expr_to_outputform_text_map["System`Graphics3D"] = graphics3d
+
+
+def grid_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    if len(expr.elements) == 0:
+        raise IsNotGrid
+    if len(expr.elements) > 1 and not expr.elements[1].has_form(
+        ["Rule", "RuleDelayed"], 2
+    ):
+        raise IsNotGrid
+    if not expr.elements[0].has_form("List", None):
+        raise IsNotGrid
+
+    elements = expr.elements[0].elements
+    rows = []
+    for idx, item in enumerate(elements):
+        if item.has_form("List", None):
+            rows.append(
+                [
+                    expression_to_outputform_text(item_elem, evaluation, form, **kwargs)
+                    for item_elem in item.elements
+                ]
+            )
+        else:
+            rows.append(expression_to_outputform_text(item, evaluation, form, **kwargs))
+
+    return grid(rows)
+
+
+expr_to_outputform_text_map["System`Grid"] = grid_expression_to_outputform_text
+
+
+def integer_expression_to_outputform_text(
+    n: Integer, evaluation: Evaluation, form: Symbol, **kwargs
+):
+    return str(n.value)
+
+
+expr_to_outputform_text_map["System`Integer"] = integer_expression_to_outputform_text
+
+
+def list_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    result, *rest_elems = (
+        expression_to_outputform_text(elem, evaluation, form, **kwargs)
+        for elem in expr.elements
+    )
+    comma_tb = ", "
+    for next_elem in rest_elems:
+        result = result + comma_tb + next_elem
+    return "{" + result + "}"
+
+
+expr_to_outputform_text_map["System`List"] = list_expression_to_outputform_text
+
+
+def mathmlform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    #  boxes = format_element(expr.elements[0], evaluation, form)
+    boxes = Expression(
+        Symbol("System`MakeBoxes"), expr.elements[0], SymbolStandardForm
+    ).evaluate(evaluation)
+    return boxes.boxes_to_mathml()  # type: ignore[union-attr]
+
+
+expr_to_outputform_text_map[
+    "System`MathMLForm"
+] = mathmlform_expression_to_outputform_text
+
+
+def matrixform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    # return parenthesize(tableform_expression_to_outputform_text(expr, evaluation, form, **kwargs))
+    return tableform_expression_to_outputform_text(expr, evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map[
+    "System`MatrixForm"
+] = matrixform_expression_to_outputform_text
+
+
+def plus_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    elements = expr.elements
+    result = ""
+    for i, elem in enumerate(elements):
+        if elem.has_form("Times", None):
+            # If the first element is -1, remove it and use
+            # a minus sign. Otherwise, if negative, do not add a sign.
+            first = elem.elements[0]
+            if isinstance(first, Integer):
+                if first.value == -1:
+                    result = (
+                        result
+                        + " - "
+                        + expression_to_outputform_text(
+                            Expression(SymbolTimes, *elem.elements[1:]),
+                            evaluation,
+                            form,
+                            **kwargs,
+                        )
+                    )
+                    continue
+                elif first.value < 0:
+                    result = (
+                        result
+                        + " "
+                        + expression_to_outputform_text(
+                            elem, evaluation, form, **kwargs
+                        )
+                    )
+                    continue
+            elif isinstance(first, Real):
+                if first.value < 0:
+                    result = (
+                        result
+                        + " "
+                        + expression_to_outputform_text(
+                            elem, evaluation, form, **kwargs
+                        )
+                    )
+                    continue
+            result = (
+                result
+                + " + "
+                + expression_to_outputform_text(elem, evaluation, form, **kwargs)
+            )
+            ## TODO: handle complex numbers?
+        else:
+            elem_txt = expression_to_outputform_text(elem, evaluation, form, **kwargs)
+            if (compare_precedence(elem, 310) or -1) < 0:
+                elem_txt = parenthesize(elem_txt)
+                result = result + " + " + elem_txt
+            elif i == 0 or (
+                (isinstance(elem, Integer) and elem.value < 0)
+                or (isinstance(elem, Real) and elem.value < 0)
+            ):
+                result = result + elem_txt
+            else:
+                result = (
+                    result
+                    + " + "
+                    + expression_to_outputform_text(elem, evaluation, form, **kwargs)
+                )
+    return result
+
+
+expr_to_outputform_text_map["System`Plus"] = plus_expression_to_outputform_text
+
+
+def power_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+):
+    if len(expr.elements) != 2:
+        raise _WrongFormattedExpression
+
+    infix_form = Expression(
+        SymbolInfix,
+        ListExpression(*(expr.elements)),
+        String("^"),
+        Integer(590),
+        SymbolRight,
+    )
+    return expression_to_outputform_text(infix_form, evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map["System`Power"] = power_expression_to_outputform_text
+
+
+def pre_pos_fix_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    elements = expr.elements
+    if not (0 <= len(elements) <= 4):
+        raise _WrongFormattedExpression
+
+    group = None
+    precedence = 670
+    # Processing the first argument:
+    head = expr.get_head()
+    target = expr.elements[0]
+    if isinstance(target, Atom):
+        raise _WrongFormattedExpression
+
+    operands = list(target.elements)
+    if len(operands) != 1:
+        raise _WrongFormattedExpression
+
+    # Processing the second argument, if it is there:
+    if len(elements) > 1:
+        ops = elements[1]
+        ops_txt = [expression_to_outputform_text(ops, evaluation, form, **kwargs)]
+    else:
+        if head is SymbolPrefix:
+            default_symb = " @ "
+            ops_txt = (
+                expression_to_outputform_text(head, evaluation, form, **kwargs)
+                + default_symb
+            )
+        elif head is SymbolPostfix:
+            default_symb = " // "
+            ops_txt = default_symb + expression_to_outputform_text(
+                head, evaluation, form, **kwargs
+            )
+
+    # Processing the third argument, if it is there:
+    if len(elements) > 2:
+        if isinstance(elements[2], Integer):
+            precedence = elements[2].value
+        else:
+            raise _WrongFormattedExpression
+
+    # Processing the forth argument, if it is there:
+    if len(elements) > 3:
+        group = elements[3]
+        if group not in (SymbolNone, SymbolLeft, SymbolRight, SymbolNonAssociative):
+            raise _WrongFormattedExpression
+        if group is SymbolNone:
+            group = None
+
+    operand = operands[0]
+    cmp_precedence = compare_precedence(operand, precedence)
+    target_txt = expression_to_outputform_text(operand, evaluation, form, **kwargs)
+    if cmp_precedence is not None and cmp_precedence != -1:
+        target_txt = parenthesize(target_txt)
+
+    return ops_txt[0] + target_txt if head is SymbolPrefix else target_txt + ops_txt[0]
+
+
+expr_to_outputform_text_map["System`Prefix"] = pre_pos_fix_expression_to_outputform_text
+expr_to_outputform_text_map[
+    "System`Postfix"
+] = pre_pos_fix_expression_to_outputform_text
+
+
+def infix_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    elements = expr.elements
+    if not (0 <= len(elements) <= 4):
+        raise _WrongFormattedExpression
+
+    group = None
+    precedence = 670
+    # Processing the first argument:
+    head = expr.get_head()
+    target = expr.elements[0]
+    if isinstance(target, Atom):
+        raise _WrongFormattedExpression
+
+    operands = list(target.elements)
+
+    if len(operands) < 2:
+        raise _WrongFormattedExpression
+
+    # Processing the second argument, if it is there:
+    if len(elements) > 1:
+        ops = elements[1]
+        if head is SymbolInfix:
+            # This is not the WMA behaviour, but the Mathics current implementation requires it:
+            num_ops = 1
+            if ops.has_form("List", None):
+                num_ops = len(ops.elements)
+                ops_lst = [
+                    expression_to_outputform_text(op, evaluation, form, **kwargs)
+                    for op in ops.elements
+                ]
+            else:
+                ops_lst = [
+                    expression_to_outputform_text(ops, evaluation, form, **kwargs)
+                ]
+        elif head in (SymbolPrefix, SymbolPostfix):
+            ops_txt = [expression_to_outputform_text(ops, evaluation, form, **kwargs)]
+    else:
+        if head is SymbolInfix:
+            num_ops = 1
+            default_symb = " ~ "
+            ops_lst = [
+                default_symb
+                + expression_to_outputform_text(head, evaluation, form, **kwargs)
+                + default_symb
+            ]
+        elif head is SymbolPrefix:
+            default_symb = " @ "
+            ops_txt = (
+                expression_to_outputform_text(head, evaluation, form, **kwargs)
+                + default_symb
+            )
+        elif head is SymbolPostfix:
+            default_symb = " // "
+            ops_txt = default_symb + expression_to_outputform_text(
+                head, evaluation, form, **kwargs
+            )
+
+    # Processing the third argument, if it is there:
+    if len(elements) > 2:
+        if isinstance(elements[2], Integer):
+            precedence = elements[2].value
+        else:
+            raise _WrongFormattedExpression
+
+    # Processing the forth argument, if it is there:
+    if len(elements) > 3:
+        group = elements[3]
+        if group not in (SymbolNone, SymbolLeft, SymbolRight, SymbolNonAssociative):
+            raise _WrongFormattedExpression
+        if group is SymbolNone:
+            group = None
+
+    if head is SymbolPrefix:
+        operand = operands[0]
+        cmp_precedence = compare_precedence(operand, precedence)
+        target_txt = expression_to_outputform_text(operand, evaluation, form, **kwargs)
+        if cmp_precedence is not None and cmp_precedence != -1:
+            target_txt = parenthesize(target_txt)
+        return ops_txt[0] + target_txt
+    if head is SymbolPostfix:
+        operand = operands[0]
+        cmp_precedence = compare_precedence(operand, precedence)
+        target_txt = expression_to_outputform_text(operand, evaluation, form, **kwargs)
+        if cmp_precedence is not None and cmp_precedence != -1:
+            target_txt = parenthesize(target_txt)
+        return target_txt + ops_txt[0]
+    else:  # Infix
+        parenthesized = group in (None, SymbolRight, SymbolNonAssociative)
+        for index, operand in enumerate(operands):
+            operand_txt = str(
+                expression_to_outputform_text(operand, evaluation, form, **kwargs)
+            )
+            cmp_precedence = compare_precedence(operand, precedence)
+            if cmp_precedence is not None and (
+                cmp_precedence == -1 or (cmp_precedence == 0 and parenthesized)
+            ):
+                operand_txt = parenthesize(operand_txt)
+
+            if index == 0:
+                result = operand_txt
+                # After the first element, for lateral
+                # associativity, parenthesized is flipped:
+                if group in (SymbolLeft, SymbolRight):
+                    parenthesized = not parenthesized
+            else:
+                space = " "
+                result_lst: List[str]
+                if str(ops_lst[index % num_ops]) != " ":
+                    result_lst = [
+                        result,
+                        space,
+                        str(ops_lst[index % num_ops]),
+                        space,
+                        operand_txt,
+                    ]
+                else:
+                    result_lst = [result, space, operand_txt]
+
+        return "".join(result_lst)
+
+
+expr_to_outputform_text_map["System`Infix"] = infix_expression_to_outputform_text
+
+
+def precedenceform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    if len(expr.elements) == 2:
+        return expression_to_outputform_text(
+            expr.elements[0], evaluation, form, **kwargs
+        )
+    raise _WrongFormattedExpression
+
+
+expr_to_outputform_text_map[
+    "System`PrecedenceForm"
+] = precedenceform_expression_to_outputform_text
+
+
+def rational_expression_to_outputform_text(
+    n: Union[Rational, Expression], evaluation: Evaluation, form: Symbol, **kwargs
+):
+    if n.has_form("Rational", 2):
+        num, den = n.elements  # type: ignore[union-attr]
+    else:
+        num, den = n.numerator(), n.denominator()  # type: ignore[union-attr]
+    return _divide(num, den, evaluation, form, **kwargs)
+
+
+expr_to_outputform_text_map["System`Rational"] = rational_expression_to_outputform_text
+
+
+def real_expression_to_outputform_text(
+    n: Real, evaluation: Evaluation, form: Symbol, **kwargs
+):
+    str_n = n.make_boxes("System`OutputForm").boxes_to_text()  # type: ignore[attr-defined]
+    return str(str_n)
+
+
+expr_to_outputform_text_map["System`Real"] = real_expression_to_outputform_text
+
+
+def string_expression_to_outputform_text(
+    expr: String, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    lines = expr.value.split("\n")
+    max_len = max([len(line) for line in lines])
+    lines = [line + (max_len - len(line)) * " " for line in lines]
+    return "\n".join(lines)
+
+
+expr_to_outputform_text_map["System`String"] = string_expression_to_outputform_text
+
+
+def stringform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    strform = expr.elements[0]
+    if not isinstance(strform, String):
+        raise _WrongFormattedExpression
+
+    items = list(
+        expression_to_outputform_text(item, evaluation, form, **kwargs)
+        for item in expr.elements[1:]
+    )
+
+    curr_indx = 0
+    parts = strform.value.split("`")
+    result = str(parts[0])
+    if len(parts) == 1:
+        return result
+
+    quote_open = True
+    remaining = len(parts) - 1
+
+    for part in parts[1:]:
+        remaining -= 1
+        if quote_open:
+            if remaining == 0:
+                result = result + "`" + part
+                quote_open = False
+                continue
+            if len(part) == 0:
+                result = result + items[curr_indx]
+                continue
+            try:
+                idx = int(part)
+            except ValueError:
+                idx = None
+            if idx is not None and str(idx) == part:
+                curr_indx = idx - 1
+                result = result + items[curr_indx]
+                quote_open = False
+                continue
+            else:
+                result = result + "`" + part + "`"
+                quote_open = False
+                continue
+        else:
+            result = result + part
+            quote_open = True
+
+    return result
+
+
+expr_to_outputform_text_map[
+    "System`StringForm"
+] = stringform_expression_to_outputform_text
+
+
+def symbol_expression_to_outputform_text(
+    symb: Symbol, evaluation: Evaluation, form: Symbol, **kwargs
+):
+    return evaluation.definitions.shorten_name(symb.name)
+
+
+expr_to_outputform_text_map["System`Symbol"] = symbol_expression_to_outputform_text
+
+
+def tableform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    return grid_expression_to_outputform_text(expr, evaluation, form)
+
+
+expr_to_outputform_text_map[
+    "System`TableForm"
+] = tableform_expression_to_outputform_text
+
+
+def texform_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    #  boxes = format_element(expr.elements[0], evaluation, form)
+    boxes = Expression(
+        Symbol("System`MakeBoxes"), expr.elements[0], SymbolStandardForm
+    ).evaluate(evaluation)
+    return boxes.boxes_to_tex()  # type: ignore
+
+
+expr_to_outputform_text_map["System`TeXForm"] = texform_expression_to_outputform_text
+
+
+def times_expression_to_outputform_text(
+    expr: Expression, evaluation: Evaluation, form: Symbol, **kwargs
+) -> str:
+    elements = expr.elements
+    num: List[BaseElement] = []
+    den: List[BaseElement] = []
+    # First, split factors with integer, negative powers:
+    for elem in elements:
+        if elem.has_form("Power", 2):
+            base, exponent = elem.elements
+            if isinstance(exponent, Integer):
+                if exponent.value == -1:
+                    den.append(base)
+                    continue
+                elif exponent.value < 0:
+                    den.append(Expression(SymbolPower, base, Integer(-exponent.value)))
+                    continue
+        elif isinstance(elem, Rational):
+            num.append(elem.numerator())
+            den.append(elem.denominator())
+            continue
+        elif elem.has_form("Rational", 2):
+            elem_elements = elem.elements
+            num.append(elem_elements[0])
+            den.append(elem_elements[1])
+            continue
+
+        num.append(elem)
+
+    # If there are integer, negative powers, process as a fraction:
+    if den:
+        den_expr = den[0] if len(den) == 1 else Expression(SymbolTimes, *den)
+        num_expr = (
+            Expression(SymbolTimes, *num)
+            if len(num) > 1
+            else num[0]
+            if len(num) == 1
+            else Integer1
+        )
+        return _divide(num_expr, den_expr, evaluation, form, **kwargs)
+
+    # there are no integer negative powers:
+    if len(num) == 1:
+        return expression_to_outputform_text(num[0], evaluation, form, **kwargs)
+
+    prefactor = 1
+    result: str = ""
+    for i, elem in enumerate(num):
+        if elem is IntegerM1:
+            prefactor *= -1
+            continue
+        if isinstance(elem, Integer):
+            prefactor *= -1
+            elem = Integer(-elem.value)
+
+        elem_txt = expression_to_outputform_text(elem, evaluation, form, **kwargs)
+        if compare_precedence(elem, 400):
+            elem_txt = parenthesize(elem_txt)
+        if i == 0:
+            result = elem_txt
+        else:
+            result = result + " " + elem_txt
+    if result == "":
+        result = "1"
+    if prefactor == -1:
+        result = "-" + result
+    return result
+
+
+expr_to_outputform_text_map["System`Times"] = times_expression_to_outputform_text
diff --git a/mathics/format/text.py b/mathics/format/text.py
index 422ce940a..681017848 100644
--- a/mathics/format/text.py
+++ b/mathics/format/text.py
@@ -9,6 +9,8 @@
 from mathics.builtin.box.layout import (
     FractionBox,
     GridBox,
+    InterpretationBox,
+    PaneBox,
     RowBox,
     SqrtBox,
     StyleBox,
@@ -40,6 +42,14 @@ def string(self, **options) -> str:
 add_conversion_fn(String, string)
 
 
+def interpretation_panebox(self, **options):
+    return boxes_to_text(self.elements[0], **options)
+
+
+add_conversion_fn(InterpretationBox, interpretation_panebox)
+add_conversion_fn(PaneBox, interpretation_panebox)
+
+
 def fractionbox(self, **options) -> str:
     _options = self.box_options.copy()
     _options.update(options)
@@ -72,13 +82,15 @@ def gridbox(self, elements=None, **box_options) -> str:
         widths = [0]
 
     cells = [
-        [
-            # TODO: check if this evaluation is necessary.
-            boxes_to_text(item, **box_options).splitlines()
-            for item in row
-        ]
-        if isinstance(row, tuple)
-        else [boxes_to_text(row, **box_options).splitlines()]
+        (
+            [
+                # TODO: check if this evaluation is necessary.
+                boxes_to_text(item, **box_options).splitlines()
+                for item in row
+            ]
+            if isinstance(row, tuple)
+            else [boxes_to_text(row, **box_options).splitlines()]
+        )
         for row in items
     ]