All files / utils ParserUtils.ts

100% Statements 15/15
100% Branches 12/12
100% Functions 2/2
100% Lines 15/15

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                                                    761x                                   14x 14x 2x     12x 12x 5x     7x 7x 7x 1x     6x 6x 1x     5x                  
/**
 * Utility class for extracting information from parser contexts.
 *
 * Centralizes common patterns for getting source positions from ANTLR
 * parser contexts, providing consistent null handling across the codebase.
 */
 
import ISourcePosition from "./types/ISourcePosition";
 
/**
 * Static utility methods for parser context operations
 */
class ParserUtils {
  /**
   * Extract source position from a parser context.
   *
   * Handles null/undefined start tokens gracefully, returning 0 for
   * missing values. This is the standard pattern used throughout C-Next
   * for error reporting.
   *
   * @param ctx - Any parser context with a start token
   * @returns Position with line and column (defaults to 0 if unavailable)
   */
  static getPosition(ctx: {
    start?: { line?: number; column?: number } | null;
  }): ISourcePosition {
    return {
      line: ctx.start?.line ?? 0,
      column: ctx.start?.column ?? 0,
    };
  }
 
  /**
   * Parse a "line:column message" prefix from an error message.
   *
   * CodeGenerator validation errors embed location as "line:col message".
   * This extracts the location and returns the clean message, or defaults
   * to line 1, column 0 if no prefix is found.
   */
  static parseErrorLocation(message: string): {
    line: number;
    column: number;
    message: string;
  } {
    const colonIdx = message.indexOf(":");
    if (colonIdx < 1) {
      return { line: 1, column: 0, message };
    }
 
    const lineStr = message.substring(0, colonIdx);
    if (!/^\d+$/.test(lineStr)) {
      return { line: 1, column: 0, message };
    }
 
    const afterColon = message.substring(colonIdx + 1);
    const spaceIdx = afterColon.indexOf(" ");
    if (spaceIdx < 1) {
      return { line: 1, column: 0, message };
    }
 
    const colStr = afterColon.substring(0, spaceIdx);
    if (!/^\d+$/.test(colStr)) {
      return { line: 1, column: 0, message };
    }
 
    return {
      line: Number.parseInt(lineStr, 10),
      column: Number.parseInt(colStr, 10),
      message: afterColon.substring(spaceIdx + 1),
    };
  }
}
 
export default ParserUtils;