trigo / trigo-web /inc /tgn /tgn.jison
k-l-lambda's picture
updated
502af73
/* Trigo Game Notation Parser
* Similar as PGN (Portable Game Notation) format
*/
/* ========== Lexical Grammar ========== */
%lex
%%
\s+ /* skip whitespace */
\n /* skip newlines */
";"[^\n]* /* skip line comments */
"{"[^}]*"}" /* skip block comments */
/* Brackets */
"[" return '['
"]" return ']'
/* String literals */
\"([^\\\"]|\\.)*\" return 'STRING'
/* Tag names - Common PGN tags */
"Event" return 'TAG_EVENT'
"Site" return 'TAG_SITE'
"Date" return 'TAG_DATE'
"Round" return 'TAG_ROUND'
"Black" return 'TAG_BLACK'
"White" return 'TAG_WHITE'
"Result" return 'TAG_RESULT'
/* Trigo-specific tags */
"Board" return 'TAG_BOARD'
"Handicap" return 'TAG_HANDICAP'
"Rules" return 'TAG_RULES'
"TimeControl" return 'TAG_TIMECONTROL'
"Annotator" return 'TAG_ANNOTATOR'
"Application" return 'TAG_APPLICATION'
/* Game result symbols */
"B+" return 'RESULT_BLACK'
"W+" return 'RESULT_WHITE'
"=" return '=' /* draw */
"*" return '*' /* unknown */
/* Move notation placeholders - will be expanded later */
[1-9][0-9]* return 'NUMBER'
"." return 'DOT'
"Pass" return 'PASS'
"Resign" return 'RESIGN'
"points" return 'POINTS'
"stones" return 'STONES'
[x](?=[1-9]) return 'TIMES'
/* Coordinates for moves - will be refined */
[a-z0]+ return 'COORDINATE'
/* Generic tag name for extensibility */
[A-Z][A-Za-z0-9_]* return 'TAG_NAME'
/* End of file */
<<EOF>> return 'EOF'
/* Catch-all for unexpected characters */
. return 'INVALID'
/lex
/* ========== Grammar Rules ========== */
%%
game
: tag_section move_section EOF
{
return {
tags: $1,
moves: $2,
success: true
};
}
| tag_section EOF
{
return {
tags: $1,
moves: null,
success: true
};
}
| move_section EOF
{
return {
tags: {},
moves: $1,
success: true
};
}
| EOF
{
return {
tags: {},
moves: null,
success: true
};
}
;
/* ========== Tag Section (Metadata) ========== */
tag_section
: tag_pair -> $1
| tag_section tag_pair -> Object.assign({}, $1, $2)
;
tag_pair
: "[" tag_name STRING "]"
{
const tagName = $2;
const tagValue = $3.slice(1, -1); // Remove quotes
$$ = { [tagName]: tagValue };
}
| "[" TAG_RESULT game_result "]" -> $3
| "[" TAG_BOARD board_shape "]" -> ({[$2]: $3})
;
tag_name
: TAG_EVENT
| TAG_SITE
| TAG_DATE
| TAG_ROUND
| TAG_BLACK
| TAG_WHITE
| TAG_HANDICAP
| TAG_RULES
| TAG_TIMECONTROL
| TAG_ANNOTATOR
| TAG_APPLICATION
| TAG_NAME { $$ = yytext; }
;
/* ========== Movetext Section (Game Body) ========== */
/* PLACEHOLDER: Will be implemented in future iterations */
move_section
: move_sequence
//| move_sequence game_termination
;
move_sequence
: move_sequence_intact -> $1
| move_sequence_truncated -> $1
;
move_sequence_intact
: /* empty */ -> []
| move_sequence_intact move_round -> $1.concat([$2])
;
move_sequence_truncated
: move_sequence_intact move_round_half -> $1.concat([$2])
;
move_round
: number DOT move_action move_action -> ({ round: $1, action_black: $3, action_white: $4 })
;
move_round_half
: number DOT move_action -> ({ round: $1, action_black: $3 })
;
move_action
: PASS -> ({ type: 'pass' })
| RESIGN -> ({ type: 'resign' })
| COORDINATE
{
// Placeholder: Parse coordinate notation
$$ = {
type: 'move',
position: yytext
};
}
;
game_result
: win -> ({Result: $1})
| win conquer -> ({Result: $1, Conquer: $2})
| "=" -> ({Result: "draw"})
| "*" -> ({Result: "unknown"})
;
win
: RESULT_BLACK -> "black win"
| RESULT_WHITE -> "white win"
;
conquer
: number conquer_unit -> ({n: $1, unit: $2})
;
conquer_unit
: POINTS
| STONES
;
board_shape
: number -> [$1]
| board_shape TIMES number -> $1.concat($3)
;
number
: NUMBER -> parseInt($1)
;
%%
/* ========== Additional JavaScript Code ========== */
// Parser configuration
parser.yy = {
// Helper functions can be added here
parseError: function(str, hash) {
throw new Error('Parse error: ' + str);
}
};