home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / szachy / gnu / amyboard-3.2.pl2 / parser.l < prev    next >
Text File  |  1995-03-08  |  21KB  |  851 lines

  1. %a 9000
  2. %o 10000
  3. %e 2000
  4. %k 2500
  5. %p 7000
  6. %n 1000
  7. %{
  8. /*
  9.  * parser.l -- lex parser of algebraic chess moves for XBoard
  10.  * $Id: parser.l,v 1.21 1995/03/09 00:43:28 mann Exp $
  11.  *
  12.  * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
  13.  * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
  14.  *
  15.  * The following terms apply to Digital Equipment Corporation's copyright
  16.  * interest in XBoard:
  17.  * ------------------------------------------------------------------------
  18.  * All Rights Reserved
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose and without fee is hereby granted,
  22.  * provided that the above copyright notice appear in all copies and that
  23.  * both that copyright notice and this permission notice appear in
  24.  * supporting documentation, and that the name of Digital not be
  25.  * used in advertising or publicity pertaining to distribution of the
  26.  * software without specific, written prior permission.
  27.  *
  28.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34.  * SOFTWARE.
  35.  * ------------------------------------------------------------------------
  36.  *
  37.  * The following terms apply to the enhanced version of XBoard distributed
  38.  * by the Free Software Foundation:
  39.  * ------------------------------------------------------------------------
  40.  * This program is free software; you can redistribute it and/or modify
  41.  * it under the terms of the GNU General Public License as published by
  42.  * the Free Software Foundation; either version 2 of the License, or
  43.  * (at your option) any later version.
  44.  *
  45.  * This program is distributed in the hope that it will be useful,
  46.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  47.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  48.  * GNU General Public License for more details.
  49.  *
  50.  * You should have received a copy of the GNU General Public License
  51.  * along with this program; if not, write to the Free Software
  52.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  53.  * ------------------------------------------------------------------------
  54.  */
  55.  
  56. /* This parser handles all forms of promotion.
  57.  * The parser resolves ambiguous moves by searching and check-testing.
  58.  * It also parses comments of the form [anything] or (anything).
  59.  */
  60.  
  61. #define NO_CONSTRAINT    -1
  62. #undef YYLMAX
  63. #define YYLMAX            4096
  64. #define UNPUT_BUF_SIZE        YYLMAX
  65.  
  66. #ifdef FLEX_SCANNER
  67. /* This is flex */
  68. #undef YY_INPUT
  69. #define YY_INPUT(buf, result, max_size) my_yy_input(buf, &result, max_size)
  70. #else
  71. /* This is lex */
  72. #undef input
  73. #undef output
  74. #undef unput
  75. #endif
  76.  
  77. /* The includes must be here, below the #undef input */
  78.  
  79. #include <ctype.h>
  80.  
  81. # if HAVE_STRING_H
  82. #  include <string.h>
  83. # else /* not HAVE_STRING_H */
  84. #  include <strings.h>
  85. # endif /* not HAVE_STRING_H */
  86.  
  87. #if HAVE_UNISTD_H
  88. # include <unistd.h>
  89. #endif
  90.  
  91. #include "common.h"
  92. #include "backend.h"
  93. #include "parser.h"
  94. #include "moves.h"
  95.  
  96. #define FakeFlags(index) \
  97.     (((((index) % 2) == 0) ? F_WHITE_ON_MOVE : 0) | F_ALL_CASTLE_OK)
  98.  
  99. extern Board    boards[MAX_MOVES];
  100. int        yyboardindex;
  101. char        currentMoveString[YYLMAX];
  102. char           *yy_text;
  103. #ifndef FLEX_SCANNER
  104. char        unputBuffer[UNPUT_BUF_SIZE];
  105. int        unputCount = 0;
  106. #endif
  107.  
  108. #ifdef FLEX_SCANNER
  109. void my_yy_input P((char *buf, int *result, int max_size));
  110. #else /*!FLEX_SCANNER*/
  111. static int input P((void));
  112. static void output P((int ch));
  113. static void unput P((int ch));
  114. #endif
  115. #undef yywrap
  116. int yywrap P((void));
  117. extern void CopyBoard P((Board to, Board from));
  118.  
  119. %}
  120. %%
  121.  
  122. [RrBbNnQqKkPp][/]?[a-h][1-8][xX:-]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)? {
  123.     /*
  124.      * Fully-qualified algebraic move, possibly with promotion
  125.      */
  126.     int skip1 = 0, skip2 = 0;
  127.     ChessSquare piece;
  128.     ChessMove result;
  129.     
  130.     /*
  131.      * remove the / 
  132.      */
  133.     if (yytext[1] == '/') skip1 = 1;
  134.     
  135.     /*
  136.      * remove the [xX:-] 
  137.      */
  138.     if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') ||
  139.     (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1;
  140.     
  141.     currentMoveString[0] = yytext[1+skip1];
  142.     currentMoveString[1] = yytext[2+skip1];
  143.     currentMoveString[2] = yytext[3+skip1+skip2];
  144.     currentMoveString[3] = yytext[4+skip1+skip2];
  145.     currentMoveString[4] = NULLCHAR;
  146.     
  147.     if (yyleng-skip1-skip2 > 5) {
  148.     if (yytext[yyleng-1] == ')') {
  149.         currentMoveString[4] = ToLower(yytext[yyleng-2]);
  150.     } else {
  151.         currentMoveString[4] = ToLower(yytext[yyleng-1]);
  152.     }
  153.     currentMoveString[5] = NULLCHAR;
  154.     }
  155.  
  156.     piece = boards[yyboardindex]
  157.       [currentMoveString[1] - '1'][currentMoveString[0] - 'a'];
  158.     if (ToLower(yytext[0]) != ToLower(PieceToChar(piece)))
  159.       return (int) BadMove;
  160.  
  161.     result = LegalityTest(boards[yyboardindex],
  162.               FakeFlags(yyboardindex), EP_UNKNOWN,
  163.               currentMoveString[1] - '1',
  164.               currentMoveString[0] - 'a',
  165.               currentMoveString[3] - '1',
  166.               currentMoveString[2] - 'a',
  167.               currentMoveString[4]);
  168.  
  169.     if (currentMoveString[4] == NULLCHAR &&
  170.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  171.     currentMoveString[4] = 'q';
  172.     currentMoveString[5] = NULLCHAR;
  173.     }
  174.  
  175.     return (int) result;
  176. }
  177.  
  178. [a-h][1-8][xX:-]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  179.     /*
  180.      * Simple algebraic move, possibly with promotion
  181.      */
  182.     int skip = 0;
  183.     ChessMove result;
  184.  
  185.     /*
  186.      * remove the [xX:-] 
  187.      */
  188.     if ((yytext[2] == 'x') || (yytext[2] == 'X') ||
  189.     (yytext[2] == '-') || (yytext[2] == ':')) skip = 1;
  190.  
  191.     currentMoveString[0] = yytext[0];
  192.     currentMoveString[1] = yytext[1];
  193.     currentMoveString[2] = yytext[2+skip];
  194.     currentMoveString[3] = yytext[3+skip];
  195.     currentMoveString[4] = NULLCHAR;
  196.  
  197.     if (yyleng-skip > 4) {
  198.     if (yytext[yyleng-1] == ')') {
  199.         currentMoveString[4] = ToLower(yytext[yyleng-2]);
  200.     } else {
  201.         currentMoveString[4] = ToLower(yytext[yyleng-1]);
  202.     }
  203.     currentMoveString[5] = NULLCHAR;
  204.     }
  205.  
  206.     result = LegalityTest(boards[yyboardindex],
  207.               FakeFlags(yyboardindex), EP_UNKNOWN,
  208.               currentMoveString[1] - '1',
  209.               currentMoveString[0] - 'a',
  210.               currentMoveString[3] - '1',
  211.               currentMoveString[2] - 'a',
  212.               currentMoveString[4]);
  213.  
  214.     if (currentMoveString[4] == NULLCHAR &&
  215.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  216.     currentMoveString[4] = 'q';
  217.     currentMoveString[5] = NULLCHAR;
  218.     }
  219.  
  220.     return (int) result;
  221. }
  222.  
  223. [a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  224.     /*
  225.      * Pawn move, possibly with promotion
  226.      */
  227.     DisambiguateClosure cl;
  228.     int skip = 0;
  229.  
  230.     /* remove the =() */
  231.     if (yytext[2] == '=') skip++;
  232.     if (yytext[2+skip] == '(') skip++;
  233.  
  234.     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
  235.     cl.rfIn = -1;
  236.     cl.ffIn = yytext[0] - 'a';
  237.     cl.rtIn = yytext[1] - '1';
  238.     cl.ftIn = yytext[0] - 'a';
  239.     cl.promoCharIn = yytext[2+skip];
  240.     Disambiguate(boards[yyboardindex],
  241.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  242.  
  243.     currentMoveString[0] = cl.ff + 'a';
  244.     currentMoveString[1] = cl.rf + '1';
  245.     currentMoveString[2] = cl.ft + 'a';
  246.     currentMoveString[3] = cl.rt + '1';
  247.     currentMoveString[4] = cl.promoChar;
  248.     currentMoveString[5] = NULLCHAR;
  249.  
  250.     return (int) cl.kind;
  251. }
  252.  
  253.  
  254. (ab|bc|cd|de|ef|fg|gh|hg|gf|fe|ed|dc|cb|ba|([a-h][xX:-][a-h]))(=?\(?[RrBbNnQq]\)?)? {
  255.     /*
  256.      * Pawn capture, possibly with promotion, possibly ambiguous
  257.      */
  258.     DisambiguateClosure cl;
  259.     int skip1 = 0, skip2 = 0;
  260.  
  261.     /*
  262.      * remove the [xX:-] and =()
  263.      */
  264.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  265.     || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1;
  266.     if (yytext[2+skip1] == '=') skip2++;
  267.     if (yytext[2+skip1+skip2] == '(') skip2++;
  268.  
  269.  
  270.     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
  271.     cl.rfIn = -1;
  272.     cl.ffIn = yytext[0] - 'a';
  273.     cl.rtIn = -1;
  274.     cl.ftIn = yytext[1+skip1] - 'a';
  275.     cl.promoCharIn = yytext[2+skip1+skip2];
  276.     Disambiguate(boards[yyboardindex],
  277.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  278.  
  279.     currentMoveString[0] = cl.ff + 'a';
  280.     currentMoveString[1] = cl.rf + '1';
  281.     currentMoveString[2] = cl.ft + 'a';
  282.     currentMoveString[3] = cl.rt + '1';
  283.     currentMoveString[4] = cl.promoChar;
  284.     currentMoveString[5] = NULLCHAR;
  285.  
  286.     return (int) cl.kind;
  287. }
  288.  
  289. [a-h][xX:]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  290.     /*
  291.      * unambiguously abbreviated Pawn capture, possibly with promotion
  292.      */
  293.     int skip = 0;
  294.     ChessMove result;
  295.  
  296.     /*
  297.      * remove the [xX:-]
  298.      */
  299.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  300.     || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1;
  301.  
  302.     currentMoveString[0] = yytext[0];
  303.     currentMoveString[2] = yytext[1+skip];
  304.     currentMoveString[3] = yytext[2+skip];
  305.     if (WhiteOnMove(yyboardindex)) {
  306.     if (yytext[2+skip] == '1') return (int) BadMove;
  307.     currentMoveString[1] = yytext[2+skip] - 1;
  308.     } else {
  309.     if (yytext[2+skip] == '8') return (int) BadMove;
  310.     currentMoveString[1] = yytext[2+skip] + 1;
  311.     }
  312.     if (yyleng-skip > 3) {
  313.     if (yytext[yyleng-1] == ')')
  314.       currentMoveString[4] = ToLower(yytext[yyleng-2]);
  315.     else
  316.       currentMoveString[4] = ToLower(yytext[yyleng-1]);
  317.     currentMoveString[5] = NULLCHAR;
  318.     } else {
  319.     currentMoveString[4] = NULLCHAR;
  320.     }
  321.  
  322.     result = LegalityTest(boards[yyboardindex],
  323.               FakeFlags(yyboardindex), EP_UNKNOWN,
  324.               currentMoveString[1] - '1',
  325.               currentMoveString[0] - 'a',
  326.               currentMoveString[3] - '1',
  327.               currentMoveString[2] - 'a',
  328.               currentMoveString[4]);
  329.  
  330.     if (currentMoveString[4] == NULLCHAR &&
  331.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  332.     currentMoveString[4] = 'q';
  333.     currentMoveString[5] = NULLCHAR;
  334.     }
  335.  
  336.     if (result != BadMove) return (int) result;
  337.  
  338.     /* Special case: improperly written en passant capture */
  339.     if (WhiteOnMove(yyboardindex)) {
  340.     if (currentMoveString[3] == '5') {
  341.         currentMoveString[1] = '5';
  342.         currentMoveString[3] = '6';
  343.     } else {
  344.         return (int) BadMove;
  345.     }
  346.     } else {
  347.     if (currentMoveString[3] == '4') {
  348.         currentMoveString[1] = '4';
  349.         currentMoveString[3] = '3';
  350.     } else {
  351.         return (int) BadMove;
  352.     }
  353.     }
  354.  
  355.     result = LegalityTest(boards[yyboardindex],
  356.               FakeFlags(yyboardindex), EP_UNKNOWN,
  357.               currentMoveString[1] - '1',
  358.               currentMoveString[0] - 'a',
  359.               currentMoveString[3] - '1',
  360.               currentMoveString[2] - 'a',
  361.               currentMoveString[4]);
  362.  
  363.     if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant)
  364.       return (int) result;
  365.     else
  366.       return (int) BadMove;
  367. }
  368.  
  369. [RrBbNnQqKk][xX:-]?[a-h][1-8]  {
  370.     /*
  371.      * piece move, possibly ambiguous
  372.      */
  373.     DisambiguateClosure cl;
  374.     int skip = 0;
  375.  
  376.     /*
  377.      * remove the [xX:-]
  378.      */
  379.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  380.     || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1;
  381.  
  382.     if (WhiteOnMove(yyboardindex)) {
  383.     cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
  384.     } else {
  385.     cl.pieceIn = CharToPiece(ToLower(yytext[0]));
  386.     }
  387.     cl.rfIn = -1;
  388.     cl.ffIn = -1;
  389.     cl.rtIn = yytext[2+skip] - '1';
  390.     cl.ftIn = yytext[1+skip] - 'a';
  391.     cl.promoCharIn = NULLCHAR;
  392.     Disambiguate(boards[yyboardindex],
  393.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  394.  
  395.     currentMoveString[0] = cl.ff + 'a';
  396.     currentMoveString[1] = cl.rf + '1';
  397.     currentMoveString[2] = cl.ft + 'a';
  398.     currentMoveString[3] = cl.rt + '1';
  399.     currentMoveString[4] = cl.promoChar;
  400.     currentMoveString[5] = NULLCHAR;
  401.  
  402.     return (int) cl.kind;
  403. }
  404.  
  405. [RrBbNnQqKk][a-h1-8][xX:-]?[a-h][1-8]    {
  406.     /*
  407.      * piece move with rank or file disambiguator
  408.      */
  409.     DisambiguateClosure cl;
  410.     int skip = 0;
  411.  
  412.     /*
  413.      * remove the [xX:-]
  414.      */
  415.     if ((yytext[2] == 'x') || (yytext[2] == 'X')
  416.     || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1;
  417.  
  418.     if (WhiteOnMove(yyboardindex)) {
  419.     cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
  420.     } else {
  421.     cl.pieceIn = CharToPiece(ToLower(yytext[0]));
  422.     }
  423.     if (isalpha(yytext[1])) {
  424.     cl.rfIn = -1;
  425.     cl.ffIn = yytext[1] - 'a';
  426.     } else {
  427.     cl.rfIn = yytext[1] - '1';
  428.     cl.ffIn = -1;
  429.     }
  430.     cl.rtIn = yytext[3+skip] - '1';
  431.     cl.ftIn = yytext[2+skip] - 'a';
  432.     cl.promoCharIn = NULLCHAR;
  433.     Disambiguate(boards[yyboardindex],
  434.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  435.  
  436.     currentMoveString[0] = cl.ff + 'a';
  437.     currentMoveString[1] = cl.rf + '1';
  438.     currentMoveString[2] = cl.ft + 'a';
  439.     currentMoveString[3] = cl.rt + '1';
  440.     currentMoveString[4] = cl.promoChar;
  441.     currentMoveString[5] = NULLCHAR;
  442.  
  443.     return (int) cl.kind;
  444. }
  445.  
  446. 000|0-0-0|ooo|OOO|o-o-o|O-O-O    {
  447.     int rf, ff, rt, ft;
  448.  
  449.     if (WhiteOnMove(yyboardindex)) {
  450.     if (boards[yyboardindex][0][3] == WhiteKing) {
  451.         /* ICS wild castling */
  452.         strcpy(currentMoveString, "d1f1");
  453.         rf = 0;
  454.         ff = 3;
  455.         rt = 0;
  456.         ft = 5;
  457.     } else {
  458.         strcpy(currentMoveString, "e1c1");
  459.         rf = 0;
  460.         ff = 4;
  461.         rt = 0;
  462.         ft = 2;
  463.     }
  464.     } else{ 
  465.     if (boards[yyboardindex][7][3] == BlackKing) {
  466.         /* ICS wild castling */
  467.         strcpy(currentMoveString, "d8f8");
  468.         rf = 7;
  469.         ff = 3;
  470.         rt = 7;
  471.         ft = 5;
  472.     } else {
  473.         strcpy(currentMoveString, "e8c8");
  474.         rf = 7;
  475.         ff = 4;
  476.         rt = 7;
  477.         ft = 2;
  478.     }
  479.     }
  480.     return (int) LegalityTest(boards[yyboardindex],
  481.                   FakeFlags(yyboardindex), EP_UNKNOWN,
  482.                   rf, ff, rt, ft, NULLCHAR);
  483. }
  484.  
  485. 00|0-0|oo|OO|o-o|O-O    {
  486.     int rf, ff, rt, ft;
  487.  
  488.     if (WhiteOnMove(yyboardindex)) {
  489.     if (boards[yyboardindex][0][3] == WhiteKing) {
  490.         /* ICS wild castling */
  491.         strcpy(currentMoveString, "d1b1");
  492.         rf = 0;
  493.         ff = 3;
  494.         rt = 0;
  495.         ft = 1;
  496.     } else {
  497.         strcpy(currentMoveString, "e1g1");
  498.         rf = 0;
  499.         ff = 4;
  500.         rt = 0;
  501.         ft = 6;
  502.     }
  503.     } else {
  504.     if (boards[yyboardindex][7][3] == BlackKing) {
  505.         /* ICS wild castling */
  506.         strcpy(currentMoveString, "d8b8");
  507.         rf = 7;
  508.         ff = 3;
  509.         rt = 7;
  510.         ft = 1;
  511.     } else {
  512.         strcpy(currentMoveString, "e8g8");
  513.         rf = 7;
  514.         ff = 4;
  515.         rt = 7;
  516.         ft = 6;
  517.     }
  518.     }
  519.     return (int) LegalityTest(boards[yyboardindex],
  520.                   FakeFlags(yyboardindex), EP_UNKNOWN,
  521.                   rf, ff, rt, ft, NULLCHAR);
  522. }
  523.  
  524. [Rr](esign|ESIGN)([Ss]|[Ee][Dd])?  {
  525.     if (WhiteOnMove(yyboardindex))
  526.       return (int) BlackWins;
  527.     else
  528.       return (int) WhiteWins;
  529. }
  530.  
  531. [Ww](hite|HITE)?" "(([Rr](esign|ESIGN))|([Ff](orfeit|ORFEIT)))([Ss]|[Ee][Dd])?  {
  532.     return (int) BlackWins;
  533. }
  534.  
  535. [Bb](lack|LACK)?" "(([Rr](esign|ESIGN))|([Ff](orfeit|ORFEIT)))([Ss]|[Ee][Dd])?  {
  536.     return (int) WhiteWins;
  537. }
  538.  
  539. [Ww](hite|HITE)?" "[Aa](sserts|SSERTS)" "([aA]" ")?[Ww](in|IN)  {
  540.     return (int) WhiteWins;
  541. }
  542.  
  543. [Bb](lack|LACK)?" "[Aa](sserts|SSERTS)" "([aA]" ")?[Ww](in|IN)  {
  544.     return (int) BlackWins;
  545. }
  546.  
  547. ([Ww](hite|HITE)|[Bb](lack|LACK))" "[dD](isconnect|ISCONNECT)([Ss]|[Ee][Dd]) {
  548.     return (int) GameUnfinished;
  549. }
  550.  
  551. [Ss](talemate|TALEMATE)  {
  552.     return (int) GameIsDrawn;
  553. }
  554.  
  555. "+-+"  {
  556.     return (int) GameIsDrawn;
  557. }
  558.  
  559. ([Cc](heck|HECK))?[Mm](ate|ATE)  {
  560.     if (WhiteOnMove(yyboardindex))
  561.       return (int) BlackWins;
  562.     else
  563.       return (int) WhiteWins;
  564. }
  565.  
  566. "++"  {
  567.     if (WhiteOnMove(yyboardindex))
  568.       return (int) BlackWins;
  569.     else
  570.       return (int) WhiteWins;
  571. }
  572.  
  573. ([Bb](lack|LACK)?|[Ww](hite|HITE)?)" "[Oo](ffers|FFERS)" "[Dd](raw|RAW)[Nn]?  {
  574.     return (int) GameIsDrawn;
  575. }
  576.  
  577. [Dd](raw|RAW)[Nn]?(" "[Bb][Yy])?(" "[Rr](epetition|EPETITION)|" "[Aa](gree|GREE)([Dd]|(ment|MENT))?) {
  578.     return (int) GameIsDrawn;
  579. }
  580.  
  581. [Dd](raw|RAW)[Nn]?(" (".*")")?  {
  582.     return (int) GameIsDrawn;
  583. }
  584.  
  585. [Ww](hite|HITE)?(" "[Ww][IiOo][Nn][Ss]?(" "[Oo][Nn]" "[Tt](ime|IME))?(" (".*")")?|" "[Mm](ates|ATES))? { 
  586.     return (int) WhiteWins;
  587. }
  588.  
  589. [Bb](lack|LACK)?(" "[Ww][IiOo][Nn][Ss]?(" "[Oo][Nn]" "[Tt](ime|IME))?(" (".*")")?|" "[Mm](ates|ATES))? { 
  590.     return (int) BlackWins;
  591. }
  592.  
  593. [Ww](hite|HITE)?" "[Ll][Oo][Ss]([Tt]|[Es][Ss])(" "[Oo][Nn]" "[Tt](ime|IME))? { 
  594.     return (int) BlackWins;
  595. }
  596.  
  597. [Bb](lack|LACK)?" "[Ll][Oo][Ss]([Tt]|[Es][Ss])(" "[Oo][Nn]" "[Tt](ime|IME))? { 
  598.     return (int) WhiteWins;
  599. }
  600.  
  601. ("{"[^\}\n]*"} ")?(1-0|"1 - 0"|"1/0"|"1 / 0"|"1:0"|"1 : 0")(" (".*")"|" {".*"}")? { 
  602.     return (int) WhiteWins;
  603. }
  604.  
  605. ("{"[^\}\n]*"} ")?(0-1|"0 - 1"|"0/1"|"0 / 1"|"0:1"|"0 : 1")(" (".*")"|" {".*"}")? { 
  606.     return (int) BlackWins;
  607. }
  608.  
  609. ("{"[^\}\n]*"} ")?("1/2"|"1 / 2")(" "?[-:]" "?("1/2"|"1 / 2"))?(" (".*")"|" {".*"}")? {
  610.     return (int) GameIsDrawn;
  611. }
  612.  
  613. ("{"[^\}\n]*"} ")?"*"(" (".*")"|" {".*"}")? {
  614.     return (int) GameUnfinished;
  615. }
  616.  
  617. [1-9][0-9]*/[. \t\n]*[a-hNnPpRrBQqKk]    {
  618.     /* move numbers */
  619.     if ((yyleng == 1) && (yytext[0] == '1'))
  620.       return (int) MoveNumberOne;
  621. }
  622.  
  623. \([0-9]+:[0-9][0-9]\)|\{[0-9]+:[0-9][0-9]\} {
  624.     /* elapsed time indication, e.g. (0:12) */ 
  625.     return (int) ElapsedTime;
  626. }
  627.  
  628. "[--"[^\]]*"--]" {
  629.     /* position diagram enclosed in [-- --] */
  630.     return (int) PositionDiagram;
  631. }
  632.  
  633. ^"{--------------"\n[^\}]*\n"--------------}"$ {
  634.     /* position diagram enclosed in {-- --} */
  635.     return (int) PositionDiagram;
  636. }
  637.  
  638. \[[ \t\n]*[A-Za-z0-9][A-Za-z0-9_+#=-]*[ \t\n]*\"[^"]*\"[ \t\n]*\] {
  639.     return (int) PGNTag;
  640. }    
  641.  
  642. [Gg](nu|NU)" "?[Cc](hess|HESS).*[Gg](ame|AME) {
  643.     return (int) GNUChessGame;
  644. }
  645.  
  646. ^[#;%]" "[^ ]*(" game file"|" position file").*$ {
  647.     return (int) XBoardGame;
  648. }
  649.  
  650. \{[^\}]*\}    {                    /* anything in {} */
  651.     return (int) Comment; 
  652. }
  653.  
  654. ;.*$ {                                          /* ; to end of line */
  655.     return (int) Comment;
  656. }
  657.  
  658. \[[^\]]*\]    {                    /* anything in [] */
  659.     return (int) Comment; 
  660. }
  661.  
  662. \([^()]*(\([^()]*\))+[^()]*\)  {           /* nested () */
  663.     return (int) Comment; 
  664. }
  665.  
  666. \([^)][^)]+\)   {                 /* >=2 chars in () */
  667.     return (int) Comment; 
  668. }       
  669.  
  670. ^[-a-zA-Z0-9]+:.*(\n[ \t]+.*)*  {
  671.         /* Skip mail headers */
  672. }
  673.  
  674. [a-zA-Z0-9'-]+            {
  675.         /* Skip random words */
  676. }
  677.  
  678. .|"\n"                {
  679.         /* Skip everything else */
  680. }
  681.  
  682. %%
  683.  
  684.  
  685. static char *StringToLex;
  686.  
  687. #ifndef FLEX_SCANNER
  688. static FILE *lexFP;
  689.  
  690. static int input()
  691. {
  692.     int ret;
  693.     
  694.     if (StringToLex != NULL) {
  695.     ret = *StringToLex;
  696.     if (ret == NULLCHAR)
  697.       ret = EOF;
  698.     else
  699.       StringToLex++;
  700.     } else if (unputCount > 0) {
  701.     ret = unputBuffer[--unputCount];
  702.     } else {
  703.     ret = fgetc(lexFP);
  704.     }    
  705.  
  706.     if (ret == EOF) 
  707.       return 0;
  708.     else
  709.       return ret;
  710. }
  711.  
  712. static void output(ch)
  713.      int ch;
  714. {
  715.     fprintf(stderr, "PARSER BUG: unmatched character '%c' (0%o)\n",
  716.         ch, ch);
  717. }
  718.  
  719. static void unput(ch)
  720.      int ch;
  721. {
  722.     if (ch == 0) return;
  723.     if (StringToLex != NULL) {
  724.     StringToLex--;
  725.     } else {
  726.     if (unputCount >= UNPUT_BUF_SIZE)
  727.       fprintf(stderr, "PARSER BUG: unput buffer overflow '%c' (0%o)\n",
  728.           ch, ch);
  729.     unputBuffer[unputCount++] = ch;
  730.     }
  731. }
  732.  
  733. /* Get ready to lex from a new file.  Kludge below sticks
  734.    an artificial newline at the front of the file, which the
  735.    above grammar ignores, but which makes ^ at start of pattern
  736.    match at the real start of the file.
  737. */
  738. void yynewfile(f)
  739.      FILE *f;
  740. {
  741.     yy_text = (char *) yytext;
  742.     lexFP = f;
  743.     StringToLex = NULL;
  744.     unputCount = 0;
  745.     unput('\n'); /* kludge */
  746. }
  747.  
  748. /* Get ready to lex from a string.  ^ at start of pattern WON'T
  749.    match at the start of the string!
  750. */
  751. void yynewstr(s)
  752.      char *s;
  753. {
  754.     yy_text = (char *) yytext;
  755.     lexFP = NULL;
  756.     StringToLex = s;
  757.     unputCount = 0;
  758. }
  759. #endif /*!FLEX_SCANNER*/
  760.  
  761. #ifdef FLEX_SCANNER
  762. void my_yy_input(buf, result, max_size)
  763.      char *buf;
  764.      int *result;
  765.      int max_size;
  766. {
  767.     int count;
  768.  
  769.     if (StringToLex != NULL) {
  770.     count = 0;
  771.     while (*StringToLex != NULLCHAR) {
  772.         *buf++ = *StringToLex++;
  773.         count++;
  774.     }
  775.     *result = count;
  776.     return;
  777.     } else {
  778.     count = fread(buf, 1, max_size, yyin);
  779.     if (count == 0) {
  780.         *result = YY_NULL;
  781.     } else {
  782.         *result = count;
  783.     }
  784.     return;
  785.     }    
  786. }
  787.  
  788. static YY_BUFFER_STATE my_file_buffer = NULL;
  789.  
  790. void yynewstr(s)
  791.      char *s;
  792. {
  793.     yy_text = (char *) yytext;
  794.     if (my_file_buffer != NULL)
  795.       yy_delete_buffer(my_file_buffer);
  796.     StringToLex = s;
  797.     my_file_buffer = yy_create_buffer(stdin, YY_BUF_SIZE);
  798.     yy_switch_to_buffer(my_file_buffer);
  799. }
  800.  
  801. void yynewfile(f)
  802.      FILE *f;
  803. {
  804.     yy_text = (char *) yytext;
  805.     if (my_file_buffer != NULL)
  806.       yy_delete_buffer(my_file_buffer);
  807.     StringToLex = NULL;
  808.     my_file_buffer = yy_create_buffer(f, YY_BUF_SIZE);
  809.     yy_switch_to_buffer(my_file_buffer);
  810. }
  811. #endif /*FLEX_SCANNER*/
  812.  
  813. int yywrap()
  814. {
  815.     return TRUE;
  816. }
  817.  
  818. /* Parse a move from the given string s */
  819. /* ^ at start of pattern WON'T work here unless using flex */
  820. ChessMove yylexstr(boardIndex, s)
  821.      int boardIndex;
  822.      char *s;
  823. {
  824.     ChessMove ret;
  825.     char *oldStringToLex;
  826. #ifdef FLEX_SCANNER
  827.     YY_BUFFER_STATE buffer, oldBuffer;
  828. #endif
  829.     
  830.     yy_text = (char *) yytext;
  831.     yyboardindex = boardIndex;
  832.     oldStringToLex = StringToLex;
  833.     StringToLex = s;
  834. #ifdef FLEX_SCANNER
  835.     buffer = yy_create_buffer(stdin, YY_BUF_SIZE);
  836.     oldBuffer = YY_CURRENT_BUFFER;
  837.     yy_switch_to_buffer(buffer);
  838. #endif /*FLEX_SCANNER*/
  839.  
  840.     ret = (ChessMove) yylex();
  841.  
  842. #ifdef FLEX_SCANNER
  843.     if (oldBuffer != NULL) 
  844.       yy_switch_to_buffer(oldBuffer);
  845.     yy_delete_buffer(buffer);
  846. #endif /*FLEX_SCANNER*/
  847.     StringToLex = oldStringToLex;
  848.  
  849.     return ret;
  850. }
  851.