trigo / trigo-web /inc /tgn /tgnParser.ts
k-l-lambda's picture
updated
502af73
/**
* TGN Parser TypeScript Wrapper
*
* Wraps the jison-generated parser with TypeScript types
*
* Based on lotus project architecture:
* - Use jison npm package for grammar compilation at build time
* - Generate parser to .js file in build phase
* - Use synchronous parsing (no async needed)
* - Works in both browser and Node.js environments
*/
/**
* Parsed move action - represents a single player's action in a round
*/
export interface ParsedMoveAction {
type: "move" | "pass" | "resign";
position?: string; // ab0yz coordinate notation
}
/**
* Parsed move round - contains both black and white moves
*/
export interface ParsedMoveRound {
round: number;
action_black: ParsedMoveAction;
action_white?: ParsedMoveAction;
}
/**
* Parsed game result
*/
export interface ParsedGameResult {
Result: string; // "black win" | "white win" | "draw" | "unknown"
Conquer?: {
n: number;
unit: string; // "points" | "stones"
};
}
/**
* Parsed TGN tags (metadata)
*/
export interface ParsedTags {
Event?: string;
Site?: string;
Date?: string;
Round?: string;
Black?: string;
White?: string;
Result?: string;
Board?: number[]; // [x, y, z] or [x, y]
Handicap?: string;
Rules?: string;
TimeControl?: string;
Annotator?: string;
Application?: string;
[key: string]: string | number[] | ParsedGameResult | undefined;
}
/**
* Parser output structure
*/
export interface TGNParseResult {
tags: ParsedTags;
moves: ParsedMoveRound[] | null;
success: boolean;
}
/**
* Parser error with position information
*/
export class TGNParseError extends Error {
constructor(
message: string,
public line?: number,
public column?: number,
public hash?: any
) {
super(message);
this.name = "TGNParseError";
}
}
// Will be set by initialization code or build process
let parserModule: any = null;
/**
* Set the parser module (called by initialization code)
* This allows the pre-built parser to be used
*/
export function setParserModule(module: any): void {
parserModule = module;
}
/**
* Get the parser module
* Throws error if parser not loaded
*/
function getParser() {
if (!parserModule) {
throw new Error(
"TGN parser not loaded. Please ensure the parser has been built.\n" +
"Run: npm run build:parsers"
);
}
return parserModule;
}
/**
* Parse TGN string and return structured data
* Synchronous parsing (no async needed)
*
* @param tgnString - TGN formatted game notation
* @returns Parsed game data with tags and moves
* @throws TGNParseError if parsing fails
*/
export function parseTGN(tgnString: string): TGNParseResult {
const parser = getParser();
if (!parser.parse) {
throw new Error("TGN parser parse method not available");
}
try {
const result = parser.parse(tgnString);
return result as TGNParseResult;
} catch (error: any) {
// Wrap jison errors with our custom error type
throw new TGNParseError(
error.message || "Unknown parse error",
error.hash?.line,
error.hash?.loc?.first_column,
error.hash
);
}
}
/**
* Validate TGN string without fully parsing
* Synchronous validation (no async needed)
*
* @param tgnString - TGN formatted game notation
* @returns Object with valid flag and error message if invalid
*/
export function validateTGN(tgnString: string): { valid: boolean; error?: string } {
try {
parseTGN(tgnString);
return { valid: true };
} catch (error: any) {
return {
valid: false,
error: error.message || "Unknown validation error"
};
}
}