Skip to content

Commit b8f552d

Browse files
Implementation of some guard methods
1 parent 12bdb2f commit b8f552d

1 file changed

Lines changed: 80 additions & 15 deletions

File tree

SysML2.NET/TextualNotation/TextualNotationValidationExtensions.cs

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020

2121
namespace SysML2.NET.TextualNotation
2222
{
23+
using System.Collections.Frozen;
24+
using System.Collections.Generic;
25+
using System.Linq;
26+
2327
using SysML2.NET.Core.POCO.Core.Features;
2428
using SysML2.NET.Core.POCO.Core.Types;
2529
using SysML2.NET.Core.POCO.Kernel.Behaviors;
@@ -260,44 +264,102 @@ public static bool IsValidForActionBodyParameterMember(this IParameterMembership
260264
throw new System.NotSupportedException("IsValidForActionBodyParameterMember requires manual implementation");
261265
}
262266

267+
/// <summary>
268+
/// Keywords of the <c>ConditionalBinaryOperator</c> lexical rule
269+
/// (<c>ConditionalBinaryOperator = '??' | 'or' | 'and' | 'implies'</c>). Matches the
270+
/// operators consumed by <c>ConditionalBinaryOperatorExpression</c>.
271+
/// </summary>
272+
private static readonly FrozenSet<string> ConditionalBinaryOperators =
273+
new HashSet<string> { "??", "or", "and", "implies" }.ToFrozenSet();
274+
275+
/// <summary>
276+
/// Keywords of the <c>BinaryOperator</c> lexical rule. Matches the operators consumed by
277+
/// <c>BinaryOperatorExpression</c>.
278+
/// </summary>
279+
private static readonly FrozenSet<string> BinaryOperators =
280+
new HashSet<string>
281+
{
282+
"|", "&", "xor", "..",
283+
"==", "!=", "===", "!==",
284+
"<", ">", "<=", ">=",
285+
"+", "-", "*", "/",
286+
"%", "^", "**"
287+
}.ToFrozenSet();
288+
289+
/// <summary>
290+
/// Keywords of the <c>UnaryOperator</c> lexical rule
291+
/// (<c>UnaryOperator = '+' | '-' | '~' | 'not'</c>). Matches the operators consumed by
292+
/// <c>UnaryOperatorExpression</c>.
293+
/// </summary>
294+
private static readonly FrozenSet<string> UnaryOperators =
295+
new HashSet<string> { "+", "-", "~", "not" }.ToFrozenSet();
296+
263297
/// <summary>
264298
/// Asserts that the <see cref="IOperatorExpression"/> is valid for the ConditionalExpression rule
299+
/// <para><c>ConditionalExpression : OperatorExpression = operator='if' …</c></para>
265300
/// </summary>
266301
/// <param name="operatorExpression">The <see cref="IOperatorExpression"/></param>
267-
/// <returns>True if the expression matches the ConditionalExpression rule</returns>
302+
/// <returns>True if the expression's <c>Operator</c> is <c>"if"</c></returns>
268303
public static bool IsValidForConditionalExpression(this IOperatorExpression operatorExpression)
269304
{
270-
throw new System.NotSupportedException("IsValidForConditionalExpression requires manual implementation");
305+
return operatorExpression?.Operator == "if";
271306
}
272307

273308
/// <summary>
274309
/// Asserts that the <see cref="IOperatorExpression"/> is valid for the ConditionalBinaryOperatorExpression rule
310+
/// <para><c>operator = ConditionalBinaryOperator</c> where <c>ConditionalBinaryOperator = '??' | 'or' | 'and' | 'implies'</c></para>
275311
/// </summary>
276312
/// <param name="operatorExpression">The <see cref="IOperatorExpression"/></param>
277-
/// <returns>True if the expression matches the ConditionalBinaryOperatorExpression rule</returns>
313+
/// <returns>True if the expression's <c>Operator</c> is one of the conditional binary operators</returns>
278314
public static bool IsValidForConditionalBinaryOperatorExpression(this IOperatorExpression operatorExpression)
279315
{
280-
throw new System.NotSupportedException("IsValidForConditionalBinaryOperatorExpression requires manual implementation");
316+
return operatorExpression?.Operator is not null && ConditionalBinaryOperators.Contains(operatorExpression.Operator);
281317
}
282318

283319
/// <summary>
284320
/// Asserts that the <see cref="IOperatorExpression"/> is valid for the BinaryOperatorExpression rule
321+
/// <para><c>BinaryOperatorExpression : OperatorExpression = ownedRelationship += ArgumentMember operator = BinaryOperator ownedRelationship += ArgumentMember ownedRelationship += EmptyResultMember</c></para>
322+
/// <para>Operator match alone is not sufficient — <c>+</c> and <c>-</c> also appear in <c>UnaryOperator</c>.
323+
/// The rule emits two <c>ArgumentMember</c> entries (vs. one for unary), so the guard additionally
324+
/// requires the expression to own at least two <see cref="IParameterMembership"/> arguments.</para>
285325
/// </summary>
286326
/// <param name="operatorExpression">The <see cref="IOperatorExpression"/></param>
287327
/// <returns>True if the expression matches the BinaryOperatorExpression rule</returns>
288328
public static bool IsValidForBinaryOperatorExpression(this IOperatorExpression operatorExpression)
289329
{
290-
throw new System.NotSupportedException("IsValidForBinaryOperatorExpression requires manual implementation");
330+
if (operatorExpression?.Operator is null || !BinaryOperators.Contains(operatorExpression.Operator))
331+
{
332+
return false;
333+
}
334+
335+
// Count ArgumentMember entries only — exclude ReturnParameterMembership (the EmptyResultMember),
336+
// which is itself an IParameterMembership in the metamodel and would otherwise inflate the count.
337+
return operatorExpression.OwnedRelationship
338+
.OfType<IParameterMembership>()
339+
.Count(membership => membership is not IReturnParameterMembership) >= 2;
291340
}
292341

293342
/// <summary>
294343
/// Asserts that the <see cref="IOperatorExpression"/> is valid for the UnaryOperatorExpression rule
344+
/// <para><c>UnaryOperatorExpression : OperatorExpression = operator = UnaryOperator ownedRelationship += ArgumentMember ownedRelationship += EmptyResultMember</c></para>
345+
/// <para>Operator match alone is not sufficient — <c>+</c> and <c>-</c> also appear in <c>BinaryOperator</c>.
346+
/// The rule emits exactly one <c>ArgumentMember</c>, so the guard additionally requires the expression
347+
/// to own a single <see cref="IParameterMembership"/> argument.</para>
295348
/// </summary>
296349
/// <param name="operatorExpression">The <see cref="IOperatorExpression"/></param>
297350
/// <returns>True if the expression matches the UnaryOperatorExpression rule</returns>
298351
public static bool IsValidForUnaryOperatorExpression(this IOperatorExpression operatorExpression)
299352
{
300-
throw new System.NotSupportedException("IsValidForUnaryOperatorExpression requires manual implementation");
353+
if (operatorExpression?.Operator is null || !UnaryOperators.Contains(operatorExpression.Operator))
354+
{
355+
return false;
356+
}
357+
358+
// Count ArgumentMember entries only — exclude ReturnParameterMembership (the EmptyResultMember),
359+
// which is itself an IParameterMembership in the metamodel.
360+
return operatorExpression.OwnedRelationship
361+
.OfType<IParameterMembership>()
362+
.Count(membership => membership is not IReturnParameterMembership) == 1;
301363
}
302364

303365
/// <summary>
@@ -401,13 +463,14 @@ public static bool IsValidForTargetTransitionUsageMember(this IFeatureMembership
401463
}
402464

403465
/// <summary>
404-
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the EntryActionMember rule (StateBodyItem)
466+
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the EntryActionMember rule (StateBodyItem).
467+
/// <para><c>EntryActionMember : StateSubactionMembership = MemberPrefix kind = 'entry' …</c></para>
405468
/// </summary>
406469
/// <param name="featureMembership">The <see cref="IFeatureMembership"/></param>
407-
/// <returns>True if the membership matches the EntryActionMember rule</returns>
470+
/// <returns>True if the membership is a <see cref="IStateSubactionMembership"/> with <c>Kind == Entry</c></returns>
408471
public static bool IsValidForEntryActionMember(this IFeatureMembership featureMembership)
409472
{
410-
throw new System.NotSupportedException("IsValidForEntryActionMember requires manual implementation");
473+
return featureMembership is IStateSubactionMembership { Kind: SysML2.NET.Core.Systems.States.StateSubactionKind.Entry };
411474
}
412475

413476
/// <summary>
@@ -421,23 +484,25 @@ public static bool IsValidForEntryTransitionMemberRule(this IFeatureMembership f
421484
}
422485

423486
/// <summary>
424-
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the DoActionMember rule (StateBodyItem)
487+
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the DoActionMember rule (StateBodyItem).
488+
/// <para><c>DoActionMember : StateSubactionMembership = MemberPrefix kind = 'do' …</c></para>
425489
/// </summary>
426490
/// <param name="featureMembership">The <see cref="IFeatureMembership"/></param>
427-
/// <returns>True if the membership matches the DoActionMember rule</returns>
491+
/// <returns>True if the membership is a <see cref="IStateSubactionMembership"/> with <c>Kind == Do</c></returns>
428492
public static bool IsValidForDoActionMember(this IFeatureMembership featureMembership)
429493
{
430-
throw new System.NotSupportedException("IsValidForDoActionMember requires manual implementation");
494+
return featureMembership is IStateSubactionMembership { Kind: SysML2.NET.Core.Systems.States.StateSubactionKind.Do };
431495
}
432496

433497
/// <summary>
434-
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the ExitActionMember rule (StateBodyItem)
498+
/// Asserts that the <see cref="IFeatureMembership"/> is valid for the ExitActionMember rule (StateBodyItem).
499+
/// <para><c>ExitActionMember : StateSubactionMembership = MemberPrefix kind = 'exit' …</c></para>
435500
/// </summary>
436501
/// <param name="featureMembership">The <see cref="IFeatureMembership"/></param>
437-
/// <returns>True if the membership matches the ExitActionMember rule</returns>
502+
/// <returns>True if the membership is a <see cref="IStateSubactionMembership"/> with <c>Kind == Exit</c></returns>
438503
public static bool IsValidForExitActionMember(this IFeatureMembership featureMembership)
439504
{
440-
throw new System.NotSupportedException("IsValidForExitActionMember requires manual implementation");
505+
return featureMembership is IStateSubactionMembership { Kind: SysML2.NET.Core.Systems.States.StateSubactionKind.Exit };
441506
}
442507

443508
/// <summary>

0 commit comments

Comments
 (0)