I would like to design a custom binary operator that is normally grouped to the left. I would like it to automatically show parentheses if it is manually grouped otherwise. I want the operator to display as an infix operator. Finally, I would like to specify the Precedence of the operator with respect to other Mathematica operators.
A model for this might be the Because operator.
Because[Because[a, b], c]
Because[a, Because[b, c]]
giving on display a pair of parentheses for the abnormal grouping.
a \[Because] b \[Because] c
a \[Because] (b \[Because] c)
I would like to code an operator GR that behaves in the same manner. Unfortunately there is nothing in the Wolfram Documentation that gives any concrete help. I would think this might be a common need for mathematicians constructing or using special algebras. I'm reasonably familiar with and willing to use Box structures, but nothing I have tried works.
Here are some attempts. First using a TagBox and trying to model on Because.
ClearAll[GR];
GR::usage =
"GR[x1,x2] is a sample function to attempt a nonassociative binary \
operator.";
SyntaxInformation[GR] = {"ArgumentsPattern" -> {_, _}};
MakeBoxes[GR[x1_, x2_],
form : (StandardForm | TraditionalForm) : StandardForm] :=
RowBox[{MakeBoxes[x1, form], TagBox["GR", "Because"],
MakeBoxes[x2, form]}];
MakeExpression[
RowBox[{lhs___, x1_, TagBox["GR", "Because"], x2_, rhs___}],
form : (StandardForm | TraditionalForm)] :=
MakeExpression[
RowBox[{lhs, RowBox[{"GR", "[", x1, ",", x2, "]"}], rhs}], form]
This inserts no parentheses in the abnormal grouping.
GR[GR[x1, x2], x3]
GR[x1, GR[x2, x3]]
x1 GR x2 GR x3
x1 GR x2 GR x3
This is an attempt using TagBox and the SyntaxForm option (which does not show on the TagBox Help page but is an option). All of these attempts gave the same unparenthesized output as above.
ClearAll[GR];
GR::usage =
"GR[x1,x2] is a sample function to attempt a nonassociative binary \
operator.";
SyntaxInformation[GR] = {"ArgumentsPattern" -> {_, _}};
MakeBoxes[GR[x1_, x2_],
form : (StandardForm | TraditionalForm) : StandardForm] :=
RowBox[{MakeBoxes[x1, form],
TagBox["GR", SyntaxForm -> "\[Because]"], MakeBoxes[x2, form]}];
MakeExpression[
RowBox[{lhs___, x1_, TagBox["GR", SyntaxForm -> "\[Because]"], x2_,
rhs___}], form : (StandardForm | TraditionalForm)] :=
MakeExpression[
RowBox[{lhs, RowBox[{"GR", "[", x1, ",", x2, "]"}], rhs}], form]
And this is an attempt using InterpretationBox:
ClearAll[GR];
GR::usage =
"GR[x1,x2] is a sample function to attempt a nonassociative binary \
operator.";
SyntaxInformation[GR] = {"ArgumentsPattern" -> {_, _}};
MakeBoxes[GR[x1_, x2_],
form : (StandardForm | TraditionalForm) : StandardForm] :=
InterpretationBox[#1, #2,
SyntaxForm -> "\[Because]"] & @@ {RowBox[{MakeBoxes[x1, form],
"GR", MakeBoxes[x2, form]}], GR[x1, x2]}
None of these work and it still leaves unaddressed the problem of setting an overall Precedence for the operator.