All files / TRANSPILE/1-Analyze BinaryOperatorLevelListener.ts

100% Statements 21/21
100% Branches 2/2
100% Functions 10/10
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                                                        2086x 2086x             59993x 797x     7876x     7876x     7545x     7545x     7496x     7496x     7494x     7494x     7492x     7492x     7489x     7489x     7417x     7417x     7184x     7184x          
/**
 * Binary Operator Level Listener
 *
 * Walks every binary-operator level of the expression grammar and hands each
 * one's operand list to a callback, so an analyzer that inspects operand pairs
 * states only WHICH levels its rule governs and WHAT to check -- never the
 * grammar wiring itself.
 *
 * That wiring (which rule is a binary-operator level, and which child rule
 * supplies its operands) is a single fact about the grammar. Before this
 * existed, MixedTypeCategoryAnalyzer and BooleanOperandAnalyzer each carried a
 * copy of it, so adding a level meant editing both (Issue #1183).
 *
 * A level with fewer than two operands is not an operator application at all --
 * the grammar collapses to a single pass-through child -- so it is not
 * dispatched.
 */
 
import { ParserRuleContext } from "antlr4ng";
import { CNextListener } from "../../PARSE/2-Parse/grammar/CNextListener";
import * as Parser from "../../PARSE/2-Parse/grammar/CNextParser";
import TBinaryOperatorLevel from "./types/TBinaryOperatorLevel";
 
/**
 * Receives one binary-operator level: its operands in source order, and which
 * level produced them.
 */
type TLevelHandler = (
  operands: ParserRuleContext[],
  level: TBinaryOperatorLevel,
) => void;
 
class BinaryOperatorLevelListener extends CNextListener {
  private readonly onLevel: TLevelHandler;
 
  constructor(onLevel: TLevelHandler) {
    super();
    this.onLevel = onLevel;
  }
 
  private dispatch(
    operands: ParserRuleContext[],
    level: TBinaryOperatorLevel,
  ): void {
    if (operands.length < 2) return;
    this.onLevel(operands, level);
  }
 
  override enterMultiplicativeExpression = (
    ctx: Parser.MultiplicativeExpressionContext,
  ): void => {
    this.dispatch(ctx.unaryExpression(), "multiplicative");
  };
 
  override enterAdditiveExpression = (
    ctx: Parser.AdditiveExpressionContext,
  ): void => {
    this.dispatch(ctx.multiplicativeExpression(), "additive");
  };
 
  override enterShiftExpression = (
    ctx: Parser.ShiftExpressionContext,
  ): void => {
    this.dispatch(ctx.additiveExpression(), "shift");
  };
 
  override enterBitwiseAndExpression = (
    ctx: Parser.BitwiseAndExpressionContext,
  ): void => {
    this.dispatch(ctx.shiftExpression(), "bitwiseAnd");
  };
 
  override enterBitwiseXorExpression = (
    ctx: Parser.BitwiseXorExpressionContext,
  ): void => {
    this.dispatch(ctx.bitwiseAndExpression(), "bitwiseXor");
  };
 
  override enterBitwiseOrExpression = (
    ctx: Parser.BitwiseOrExpressionContext,
  ): void => {
    this.dispatch(ctx.bitwiseXorExpression(), "bitwiseOr");
  };
 
  override enterRelationalExpression = (
    ctx: Parser.RelationalExpressionContext,
  ): void => {
    this.dispatch(ctx.bitwiseOrExpression(), "relational");
  };
 
  override enterEqualityExpression = (
    ctx: Parser.EqualityExpressionContext,
  ): void => {
    this.dispatch(ctx.relationalExpression(), "equality");
  };
}
 
export default BinaryOperatorLevelListener;