2020
2121namespace 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