X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=parser.l;h=e78c23c0902977e6f2f1f5e0f653c1e3b8acbfb2;hb=582aeb45129ac85b911614bee1b9cdf8ff0636b5;hp=307c94876e529c68643d3dafe81f84ae44a780fd;hpb=d75e8535ef79d4267faa60491d420b1d5c79a10c;p=xboard.git diff --git a/parser.l b/parser.l index 307c948..e78c23c 100644 --- a/parser.l +++ b/parser.l @@ -178,7 +178,7 @@ extern void CopyBoard P((Board to, Board from)); %} %% -"+"?[A-Z][/]?[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Z]\)?)|=)? { +"+"?[A-Z][/]?[a-l][0-9][xX:-]?[a-l][0-9](([=/]?\(?[A-Z]\)?)|[=+])? { /* * Fully-qualified algebraic move, possibly with promotion */ @@ -215,9 +215,8 @@ extern void CopyBoard P((Board to, Board from)); } else { c = currentMoveString[4] = ToLower(yytext[yyleng-1]); } + if(c == '+' && gameInfo.variant != VariantShogi) c = currentMoveString[4] = NULLCHAR; // + means check outside Shogi currentMoveString[5] = NULLCHAR; - if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare) - return IllegalMove; /* [HGM] promotion to invalid piece */ } if (appData.debugMode) { @@ -251,8 +250,8 @@ extern void CopyBoard P((Board to, Board from)); currentMoveString[2] - AAA, currentMoveString[4]); - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotion || result == BlackPromotion)) { + if (currentMoveString[4] == NULLCHAR) { + if(result == WhitePromotion || result == BlackPromotion) { if(gameInfo.variant == VariantCourier || gameInfo.variant == VariantShatranj) currentMoveString[4] = PieceToChar(BlackFerz); else if(gameInfo.variant == VariantGreat) @@ -261,13 +260,15 @@ extern void CopyBoard P((Board to, Board from)); currentMoveString[4] = '+'; else currentMoveString[4] = PieceToChar(BlackQueen); - currentMoveString[5] = NULLCHAR; + } else if(result == WhiteNonPromotion || result == BlackNonPromotion) + currentMoveString[4] = '='; + currentMoveString[5] = NULLCHAR; } return (int) result; } -[a-l][0-9][xX:-]?[a-l][0-9]((=?\(?[A-Za-z]\)?)|=)? { +[a-l][0-9][xX:-]?[a-l][0-9](([=/]?\(?[A-Za-z]\)?)|[=+])? { /* * Simple algebraic move, possibly with promotion * [HGM] Engine moves are received in this format, with lower-case promoChar! @@ -293,9 +294,8 @@ extern void CopyBoard P((Board to, Board from)); } else { c = currentMoveString[4] = ToLower(yytext[yyleng-1]); } + if(c == '+' && gameInfo.variant != VariantShogi) currentMoveString[4] = NULLCHAR; // + means check outside Shogi currentMoveString[5] = NULLCHAR; - if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare) - return IllegalMove; } /* [HGM] do not allow values beyond board size */ @@ -327,9 +327,10 @@ extern void CopyBoard P((Board to, Board from)); currentMoveString[4] = '+'; // Queen might not be defined in mini variants! else currentMoveString[4] = PieceToChar(BlackQueen); - currentMoveString[5] = NULLCHAR; - } - } else if(appData.testLegality && // strip off unnecessary and false promo characters + } else if(result == WhiteNonPromotion || result == BlackNonPromotion) + currentMoveString[4] = '='; + currentMoveString[5] = NULLCHAR; + } else if(appData.testLegality && gameInfo.variant != VariantSChess && // strip off unnecessary and false promo characters !(result == WhitePromotion || result == BlackPromotion || result == WhiteNonPromotion || result == BlackNonPromotion)) currentMoveString[4] = NULLCHAR; @@ -339,7 +340,7 @@ extern void CopyBoard P((Board to, Board from)); [A-L][0-9][xX:-]?[A-L][0-9] { /* * Simple algebraic move, in capitals - * [HGM] Engine moves are received in this format, with lower-case promoChar! + * [HGM] Some Xiangqi engines use this format ('ICCS notation'). So no promotions! */ int skip = 0; ChessMove result; @@ -375,26 +376,15 @@ extern void CopyBoard P((Board to, Board from)); currentMoveString[2] - AAA, currentMoveString[4]); - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotion || result == BlackPromotion)) { - if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) - currentMoveString[4] = PieceToChar(BlackFerz); - else if(gameInfo.variant == VariantGreat) - currentMoveString[4] = PieceToChar(BlackMan); - else - currentMoveString[4] = PieceToChar(BlackQueen); - currentMoveString[5] = NULLCHAR; - } - return (int) result; } -[a-l][0-9]((=?\(?[A-Za-z]\)?)|=)? { +[a-l][0-9]((=?\(?[A-Za-z]\)?)|[=+])? { /* * Pawn move, possibly with promotion */ DisambiguateClosure cl; - int skip = 0; char c; + int skip = 0; if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ @@ -407,7 +397,8 @@ extern void CopyBoard P((Board to, Board from)); cl.ffIn = yytext[0] - AAA; cl.rtIn = yytext[1] - ONE; cl.ftIn = yytext[0] - AAA; - c = cl.promoCharIn = ToLower(yytext[2+skip]); + cl.promoCharIn = ToLower(yytext[2+skip]); + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.rtIn >= BOARD_HEIGHT || @@ -416,10 +407,6 @@ extern void CopyBoard P((Board to, Board from)); cl.ftIn < BOARD_LEFT ) return ImpossibleMove; - if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare) - return IllegalMove; - - Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl); currentMoveString[0] = cl.ff + AAA; @@ -438,7 +425,7 @@ extern void CopyBoard P((Board to, Board from)); * Pawn capture, possibly with promotion, possibly ambiguous */ DisambiguateClosure cl; - int skip1 = 0, skip2 = 0; char c; + int skip1 = 0, skip2 = 0; if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ @@ -462,7 +449,8 @@ extern void CopyBoard P((Board to, Board from)); cl.ffIn = yytext[0] - AAA; cl.rtIn = -1; cl.ftIn = yytext[1+skip1] - AAA; - c = cl.promoCharIn = yytext[2+skip1+skip2]; + cl.promoCharIn = yytext[2+skip1+skip2]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.ffIn >= BOARD_RGHT || @@ -471,9 +459,6 @@ extern void CopyBoard P((Board to, Board from)); cl.ftIn < BOARD_LEFT ) return ImpossibleMove; - if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare) - return IllegalMove; - Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl); currentMoveString[0] = cl.ff + AAA; @@ -486,7 +471,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) cl.kind; } -[a-l][xX:]?[a-l][0-9]((=?\(?[A-Z]\)?)|ep|"e.p."|=)? { +[a-l][xX:]?[a-l][0-9]((=?\(?[A-Z]\)?)|ep|"e.p."|[=+])? { /* * unambiguously abbreviated Pawn capture, possibly with promotion */ @@ -542,8 +527,7 @@ extern void CopyBoard P((Board to, Board from)); else c = currentMoveString[4] = ToLower(yytext[yyleng-1]); currentMoveString[5] = NULLCHAR; - if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare) - return IllegalMove; + if(c == '+' && gameInfo.variant != VariantShogi) c = currentMoveString[4] = NULLCHAR; // + means check outside Shogi } else { currentMoveString[4] = NULLCHAR; } @@ -556,15 +540,19 @@ extern void CopyBoard P((Board to, Board from)); currentMoveString[2] - AAA, currentMoveString[4]); - if (currentMoveString[4] == NULLCHAR && - (result == WhitePromotion || result == BlackPromotion)) { + if (currentMoveString[4] == NULLCHAR) { + if(result == WhitePromotion || result == BlackPromotion) { currentMoveString[4] = PieceToChar(BlackQueen); // [HGM] shatranj: take care of variants without Queen if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk) currentMoveString[4] = PieceToChar(BlackFerz); if(gameInfo.variant == VariantGreat) currentMoveString[4] = PieceToChar(BlackMan); - currentMoveString[5] = NULLCHAR; + if(gameInfo.variant == VariantShogi) + currentMoveString[4] = '+'; + } else if(result == WhiteNonPromotion || result == BlackNonPromotion) + currentMoveString[4] = '='; + currentMoveString[5] = NULLCHAR; } if (result != IllegalMove) return (int) result; @@ -596,11 +584,15 @@ extern void CopyBoard P((Board to, Board from)); if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant) return (int) result; - else + else { // [HGM] all very nice, but this messed up the input move that we might want to accept with legality testing off... + if (WhiteOnMove(yyboardindex)) // undo the damage + currentMoveString[1]--, currentMoveString[3]--; + else currentMoveString[1]++, currentMoveString[3]++; return (int) IllegalMove; + } } -"+"?[A-Z][xX:-]?[a-l][0-9]=? { +"+"?[A-Z][xX:-]?[a-l][0-9](([=/]?\(?[A-Z]\)?)|[=+])? { /* * piece move, possibly ambiguous */ @@ -628,8 +620,9 @@ extern void CopyBoard P((Board to, Board from)); cl.ftIn = yytext[1+skip] - AAA; cl.promoCharIn = NULLCHAR; - if(yyleng-skip > 3) /* [HGM] can have Shogi-style promotion */ - cl.promoCharIn = yytext[yyleng-1]; + if(yyleng-skip > 3 && (gameInfo.variant == VariantShogi || gameInfo.variant == VariantSChess)) /* [HGM] can have Shogi-style promotion */ + cl.promoCharIn = yytext[yyleng-1-(yytext[yyleng-1]==')')]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi if (appData.debugMode) { fprintf(debugFP, "Parser Qa1: yyleng=%d, %d(%d,%d)-(%d,%d) = %d (%c)\n", @@ -656,7 +649,7 @@ extern void CopyBoard P((Board to, Board from)); return (int) cl.kind; } -"+"?[A-Z][a-l0-9][xX:-]?[a-l][0-9]=? { +"+"?[A-Z][a-l0-9][xX:-]?[a-l][0-9](([=/]?\(?[A-Z]\)?)|[=+])? { /* * piece move with rank or file disambiguator */ @@ -694,8 +687,9 @@ extern void CopyBoard P((Board to, Board from)); cl.ftIn = yytext[2+skip] - AAA; cl.promoCharIn = NULLCHAR; - if(yyleng-skip > 4) /* [HGM] can have Shogi-style promotion */ - cl.promoCharIn = yytext[yyleng-1]; + if(yyleng-skip > 4 && (gameInfo.variant == VariantShogi || gameInfo.variant == VariantSChess)) /* [HGM] can have Shogi-style promotion */ + cl.promoCharIn = yytext[yyleng-1-(yytext[yyleng-1]==')')]; + if(cl.promoCharIn == '+' && gameInfo.variant != VariantShogi) cl.promoCharIn = NULLCHAR; // + means check outside Shogi /* [HGM] do not allow values beyond board size */ if(cl.rtIn >= BOARD_HEIGHT || @@ -828,7 +822,10 @@ extern void CopyBoard P((Board to, Board from)); rf, ff, rt, ft, NULLCHAR); } -[A-Z][@*][a-l][0-9] { +[A-Za-z][@*][a-l][0-9] { + + if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */ + /* Bughouse piece drop. */ currentMoveString[1] = '@'; currentMoveString[2] = yytext[2]; @@ -905,26 +902,27 @@ extern void CopyBoard P((Board to, Board from)); return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins); } -("{"[^\}\n]*"} ")?(1-0|"1 - 0"|"1/0"|"1 / 0"|"1:0"|"1 : 0")(" (".*")"|" {".*"}")? { +("{"[^\}]*"}"[ \n])?(1-0|"1 - 0"|"1/0"|"1 / 0"|"1:0"|"1 : 0")(" (".*")"|" {".*"}")? { return (int) WhiteWins; } -("{"[^\}\n]*"} ")?(0-1|"0 - 1"|"0/1"|"0 / 1"|"0:1"|"0 : 1")(" (".*")"|" {".*"}")? { +("{"[^\}]*"}"[ \n])?(0-1|"0 - 1"|"0/1"|"0 / 1"|"0:1"|"0 : 1")(" (".*")"|" {".*"}")? { return (int) BlackWins; } -("{"[^\}\n]*"} ")?("1/2"|"1 / 2")(" "?[-:]" "?("1/2"|"1 / 2"))?(" (".*")"|" {".*"}")? { +("{"[^\}]*"}"[ \n])?("1/2"|"1 / 2")(" "?[-:]" "?("1/2"|"1 / 2"))?(" (".*")"|" {".*"}")? { return (int) GameIsDrawn; } -("{"[^\}\n]*"} ")?"*"(" (".*")"|" {".*"}")? { +("{"[^\}]*"}"[ \n])?"*"(" (".*")"|" {".*"}")? { return (int) GameUnfinished; } -[1-9][0-9]*/"."?[ \t\n]*[a-lNnPpRrBQqKACFEWDGHOo] { +[1-9][0-9]*/"."?[ \t\n]*[a-lnprqoA-Z+] { /* move numbers */ if ((yyleng == 1) && (yytext[0] == '1')) return (int) MoveNumberOne; + else return (int) Nothing; // [HGM] make sure something is returned, for gathering parsed text } \([0-9]+:[0-9][0-9](\.[0-9]+)?\)|\{[0-9]+:[0-9][0-9](\.[0-9]+)?\} { @@ -970,24 +968,24 @@ extern void CopyBoard P((Board to, Board from)); return (int) Comment; } -\([^()]*(\([^()]*(\([^()]*(\([^()]*\)[^()]*)*\)[^()]*)*\)[^()]*)+[^()]*\) { /* very nested () */ - return (int) Comment; +\( { /* Opening parentheses */ + return (int) Open; } -\([^)][^)]+\) { /* >=2 chars in () */ - return (int) Comment; +\) { /* closing parentheses */ + return (int) Close; } ^[-a-zA-Z0-9]+:" ".*(\n[ \t]+.*)* { - /* Skip mail headers */ + return (int) Nothing; /* Skip mail headers */ } [a-zA-Z0-9'-]+ { - /* Skip random words */ + return (int) Nothing; /* Skip random words */ } .|\n { - /* Skip everything else */ + return (int) Nothing; /* Skip everything else */ } %% @@ -1168,7 +1166,7 @@ ChessMove yylexstr(boardIndex, s, text, len) yy_switch_to_buffer(buffer); #endif /*FLEX_SCANNER*/ - ret = (ChessMove) yylex(); + ret = (ChessMove) Myylex(); strncpy(text, yy_text, len-1); // [HGM] vari: yy_text is not available to caller after buffer switch ?!? text[len-1] = NULLCHAR; @@ -1181,3 +1179,23 @@ ChessMove yylexstr(boardIndex, s, text, len) return ret; } + +int Myylex() +{ // [HGM] wrapper for yylex, which treats nesting of parentheses + int symbol, nestingLevel = 0, i=0; + char *p; + static char buf[256*MSG_SIZ]; + buf[0] = NULLCHAR; + do { // eat away anything not at level 0 + symbol = yylex(); + if(symbol == Open) nestingLevel++; + if(nestingLevel) { // save all parsed text between (and including) the () + for(p=yytext; *p && i<256*MSG_SIZ-2;) buf[i++] = *p++; + buf[i] = NULLCHAR; + } + if(symbol == 0) break; // ran into EOF + if(symbol == Close) symbol = Comment, nestingLevel--; + } while(nestingLevel || symbol == Nothing); + yy_text = buf[0] ? buf : (char*)yytext; + return symbol; +}