Skip to content

Commit b0e7168

Browse files
authored
Place set union and minus at same precedence, place xor above or in precedence, fix chained comparison parsing (#658)
1 parent 1aaa925 commit b0e7168

29 files changed

Lines changed: 1322 additions & 1540 deletions

Sources/AngouriMath/Convenience/MathS.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2380,7 +2380,7 @@ public static IEnumerable<Entity> TaylorTerms(Entity expr, params (Variable expr
23802380
/// Unhandled exception. AngouriMath.Core.Exceptions.CannotEvalException
23812381
/// </code>
23822382
/// </example>
2383-
public static Entity Equality(Entity a, Entity b) => a.Equalizes(b);
2383+
public static Entity Equality(Entity a, Entity b) => a.EqualTo(b);
23842384

23852385
/// <param name="a">Left argument node of which the greater than node will be taken</param>
23862386
/// <param name="b">Right argument node of which the greater than node function will be taken</param>

Sources/AngouriMath/Core/Antlr/AngouriMath.g

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,23 @@ Sets
114114
115115
set_operator_intersection returns[Entity value]
116116
: left = sum_expression { $value = $left.value; }
117-
(
118-
'intersect' right = sum_expression { $value = $value.Intersect($right.value); } |
119-
'/\\' right = sum_expression { $value = $value.Intersect($right.value); }
117+
( 'intersect' right = sum_expression { $value = $value.Intersect($right.value); }
118+
| '/\\' right = sum_expression { $value = $value.Intersect($right.value); }
120119
)*
121120
;
122121
123-
set_operator_union returns[Entity value]
122+
set_operator_union_setsubtraction returns[Entity value]
124123
: left = set_operator_intersection { $value = $left.value; }
125-
(
126-
'unite' right = set_operator_intersection { $value = $value.Unite($right.value); } |
127-
'\\/' right = set_operator_intersection { $value = $value.Unite($right.value); }
128-
)*
129-
;
130-
131-
set_operator_setsubtraction returns[Entity value]
132-
: left = set_operator_union { $value = $left.value; }
133-
(
134-
'setsubtract' right = set_operator_union { $value = $value.SetSubtract($right.value); } |
135-
'\\' right = set_operator_union { $value = $value.SetSubtract($right.value); }
124+
( 'unite' right = set_operator_intersection { $value = $value.Unite($right.value); }
125+
| '\\/' right = set_operator_intersection { $value = $value.Unite($right.value); }
126+
| 'setsubtract' right = set_operator_intersection { $value = $value.SetSubtract($right.value); }
127+
| '\\' right = set_operator_intersection { $value = $value.SetSubtract($right.value); }
136128
)*
137129
;
138130
139131
in_operator returns[Entity value]
140-
: m1 = set_operator_setsubtraction { $value = $m1.value; }
141-
('in' m2 = set_operator_setsubtraction { $value = $value.In($m2.value); })*
132+
: m1 = set_operator_union_setsubtraction { $value = $m1.value; }
133+
('in' m2 = set_operator_union_setsubtraction { $value = $value.In($m2.value); })*
142134
;
143135
144136
@@ -148,42 +140,50 @@ Equality/inequality nodes
148140
149141
*/
150142
151-
inequality_expression returns[Entity value]
152-
: m1 = in_operator { $value = $m1.value; }
143+
comparison_expression returns[Entity value]
144+
@init { List<Entity> terms = []; List<string> operators = []; }
145+
: m1 = in_operator { terms.Add($m1.value); }
153146
(
154-
'>=' m2 = in_operator { $value = $value >= $m2.value; } |
155-
'<=' m2 = in_operator { $value = $value <= $m2.value; } |
156-
'>' m2 = in_operator { $value = $value > $m2.value; } |
157-
'<' m2 = in_operator { $value = $value < $m2.value; } |
158-
'equalizes' m2 = in_operator { $value = MathS.Equality($value, $m2.value); })*
147+
('>=' { operators.Add(">="); } |
148+
'<=' { operators.Add("<="); } |
149+
'>' { operators.Add(">"); } |
150+
'<' { operators.Add("<"); } |
151+
'=' { operators.Add("="); } |
152+
'<>' { operators.Add("<>"); })
153+
m2 = in_operator { terms.Add($m2.value); }
154+
)*
155+
{
156+
if (terms.Count == 1)
157+
$value = terms[0];
158+
else
159+
// Create chain: a < b = c < d becomes (a < b) and (b = c) and (c < d)
160+
for (int i = 0; i < operators.Count; i++)
161+
{
162+
var connective = operators[i] switch
163+
{ // Directly construct the nodes instead of using convenience methods to avoid built-in chained comparisons
164+
">=" => new GreaterOrEqualf(terms[i], terms[i + 1]),
165+
"<=" => new LessOrEqualf(terms[i], terms[i + 1]),
166+
">" => new Greaterf(terms[i], terms[i + 1]),
167+
"<" => new Lessf(terms[i], terms[i + 1]),
168+
"=" => new Equalsf(terms[i], terms[i + 1]),
169+
"<>" => !new Equalsf(terms[i], terms[i + 1]),
170+
_ => throw new AngouriBugException($"Unknown operator in chained comparison: {operators[i]}")
171+
};
172+
if (i == 0) $value = connective; else $value &= connective;
173+
}
174+
}
159175
;
160176
161-
terms_list returns[List<Entity> terms]
162-
@init { $terms = new(); }
163-
: ('=' term = inequality_expression { $terms.Add($term.value); })+
164-
;
165-
166-
equality_expression returns[Entity value]
167-
: expr = inequality_expression { $value = $expr.value; } (terms_list
168-
{
169-
var list = $terms_list.terms.Prepend($value).ToArray();
170-
List<Entity> eqTerms = new();
171-
for (int i = 0; i < list.Length - 1; i++)
172-
eqTerms.Add(list[i].Equalizes(list[i + 1]));
173-
$value = eqTerms.Aggregate((eq1, eq2) => eq1 & eq2);
174-
})?
175-
;
176-
177177
/*
178178
179179
Boolean nodes
180180
181181
*/
182182
183183
negate_expression returns[Entity value]
184-
: 'not' op = equality_expression { $value = !$op.value; }
184+
: 'not' op = comparison_expression { $value = !$op.value; }
185185
| 'not' opn = negate_expression { $value = !$opn.value; }
186-
| op = equality_expression { $value = $op.value; }
186+
| op = comparison_expression { $value = $op.value; }
187187
;
188188
189189
and_expression returns[Entity value]
@@ -200,8 +200,8 @@ xor_expression returns[Entity value]
200200
201201
or_expression returns[Entity value]
202202
: m1 = xor_expression { $value = $m1.value; }
203-
('or' m2 = xor_expression { $value = $value | $m2.value; } |
204-
'|' m2 = xor_expression { $value = $value | $m2.value; })*
203+
( 'or' m2 = xor_expression { $value = $value | $m2.value; }
204+
| '|' m2 = xor_expression { $value = $value | $m2.value; })*
205205
;
206206
207207
implies_expression returns[Entity value]
@@ -218,7 +218,7 @@ Keyword nodes
218218
219219
provided_expression returns[Entity value]
220220
: expr = implies_expression { $value = $expr.value; }
221-
('provided' pred = implies_expression { $value = $value.Provided($pred.value); })*
221+
('provided' pred = provided_expression { $value = $value.Provided($pred.value); })?
222222
;
223223
224224
/*

Sources/AngouriMath/Core/Antlr/AngouriMath.interp

Lines changed: 4 additions & 7 deletions
Large diffs are not rendered by default.

Sources/AngouriMath/Core/Antlr/AngouriMath.tokens

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ WS=127
142142
'<='=15
143143
'>'=16
144144
'<'=17
145-
'equalizes'=18
146-
'='=19
145+
'='=18
146+
'<>'=19
147147
'not'=20
148148
'and'=21
149149
'&'=22

Sources/AngouriMath/Core/Antlr/AngouriMathBaseListener.cs

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -121,29 +121,17 @@ public virtual void EnterSet_operator_intersection([NotNull] AngouriMathParser.S
121121
/// <param name="context">The parse tree.</param>
122122
public virtual void ExitSet_operator_intersection([NotNull] AngouriMathParser.Set_operator_intersectionContext context) { }
123123
/// <summary>
124-
/// Enter a parse tree produced by <see cref="AngouriMathParser.set_operator_union"/>.
124+
/// Enter a parse tree produced by <see cref="AngouriMathParser.set_operator_union_setsubtraction"/>.
125125
/// <para>The default implementation does nothing.</para>
126126
/// </summary>
127127
/// <param name="context">The parse tree.</param>
128-
public virtual void EnterSet_operator_union([NotNull] AngouriMathParser.Set_operator_unionContext context) { }
128+
public virtual void EnterSet_operator_union_setsubtraction([NotNull] AngouriMathParser.Set_operator_union_setsubtractionContext context) { }
129129
/// <summary>
130-
/// Exit a parse tree produced by <see cref="AngouriMathParser.set_operator_union"/>.
130+
/// Exit a parse tree produced by <see cref="AngouriMathParser.set_operator_union_setsubtraction"/>.
131131
/// <para>The default implementation does nothing.</para>
132132
/// </summary>
133133
/// <param name="context">The parse tree.</param>
134-
public virtual void ExitSet_operator_union([NotNull] AngouriMathParser.Set_operator_unionContext context) { }
135-
/// <summary>
136-
/// Enter a parse tree produced by <see cref="AngouriMathParser.set_operator_setsubtraction"/>.
137-
/// <para>The default implementation does nothing.</para>
138-
/// </summary>
139-
/// <param name="context">The parse tree.</param>
140-
public virtual void EnterSet_operator_setsubtraction([NotNull] AngouriMathParser.Set_operator_setsubtractionContext context) { }
141-
/// <summary>
142-
/// Exit a parse tree produced by <see cref="AngouriMathParser.set_operator_setsubtraction"/>.
143-
/// <para>The default implementation does nothing.</para>
144-
/// </summary>
145-
/// <param name="context">The parse tree.</param>
146-
public virtual void ExitSet_operator_setsubtraction([NotNull] AngouriMathParser.Set_operator_setsubtractionContext context) { }
134+
public virtual void ExitSet_operator_union_setsubtraction([NotNull] AngouriMathParser.Set_operator_union_setsubtractionContext context) { }
147135
/// <summary>
148136
/// Enter a parse tree produced by <see cref="AngouriMathParser.in_operator"/>.
149137
/// <para>The default implementation does nothing.</para>
@@ -157,41 +145,17 @@ public virtual void EnterIn_operator([NotNull] AngouriMathParser.In_operatorCont
157145
/// <param name="context">The parse tree.</param>
158146
public virtual void ExitIn_operator([NotNull] AngouriMathParser.In_operatorContext context) { }
159147
/// <summary>
160-
/// Enter a parse tree produced by <see cref="AngouriMathParser.inequality_expression"/>.
161-
/// <para>The default implementation does nothing.</para>
162-
/// </summary>
163-
/// <param name="context">The parse tree.</param>
164-
public virtual void EnterInequality_expression([NotNull] AngouriMathParser.Inequality_expressionContext context) { }
165-
/// <summary>
166-
/// Exit a parse tree produced by <see cref="AngouriMathParser.inequality_expression"/>.
167-
/// <para>The default implementation does nothing.</para>
168-
/// </summary>
169-
/// <param name="context">The parse tree.</param>
170-
public virtual void ExitInequality_expression([NotNull] AngouriMathParser.Inequality_expressionContext context) { }
171-
/// <summary>
172-
/// Enter a parse tree produced by <see cref="AngouriMathParser.terms_list"/>.
173-
/// <para>The default implementation does nothing.</para>
174-
/// </summary>
175-
/// <param name="context">The parse tree.</param>
176-
public virtual void EnterTerms_list([NotNull] AngouriMathParser.Terms_listContext context) { }
177-
/// <summary>
178-
/// Exit a parse tree produced by <see cref="AngouriMathParser.terms_list"/>.
179-
/// <para>The default implementation does nothing.</para>
180-
/// </summary>
181-
/// <param name="context">The parse tree.</param>
182-
public virtual void ExitTerms_list([NotNull] AngouriMathParser.Terms_listContext context) { }
183-
/// <summary>
184-
/// Enter a parse tree produced by <see cref="AngouriMathParser.equality_expression"/>.
148+
/// Enter a parse tree produced by <see cref="AngouriMathParser.comparison_expression"/>.
185149
/// <para>The default implementation does nothing.</para>
186150
/// </summary>
187151
/// <param name="context">The parse tree.</param>
188-
public virtual void EnterEquality_expression([NotNull] AngouriMathParser.Equality_expressionContext context) { }
152+
public virtual void EnterComparison_expression([NotNull] AngouriMathParser.Comparison_expressionContext context) { }
189153
/// <summary>
190-
/// Exit a parse tree produced by <see cref="AngouriMathParser.equality_expression"/>.
154+
/// Exit a parse tree produced by <see cref="AngouriMathParser.comparison_expression"/>.
191155
/// <para>The default implementation does nothing.</para>
192156
/// </summary>
193157
/// <param name="context">The parse tree.</param>
194-
public virtual void ExitEquality_expression([NotNull] AngouriMathParser.Equality_expressionContext context) { }
158+
public virtual void ExitComparison_expression([NotNull] AngouriMathParser.Comparison_expressionContext context) { }
195159
/// <summary>
196160
/// Enter a parse tree produced by <see cref="AngouriMathParser.negate_expression"/>.
197161
/// <para>The default implementation does nothing.</para>

0 commit comments

Comments
 (0)