<?php
//require_once 'File/ChessPGN/Parser.php';
require_once dirname(__FILE__) . '/Parser.php';
class File_ChessPGN_Lexer
{
const TAGOPEN = File_ChessPGN_Parser::TAGOPEN; // [
const TAGNAME = File_ChessPGN_Parser::TAGNAME; // ]
const TAGCLOSE = File_ChessPGN_Parser::TAGCLOSE; // ]
const STRING = File_ChessPGN_Parser::STRING; // ]
const NAG = File_ChessPGN_Parser::NAG; // $1 $2, etc.
const GAMEEND = File_ChessPGN_Parser::GAMEEND; // * 1-0 0-1
const PAWNMOVE = File_ChessPGN_Parser::PAWNMOVE; // e4, e8=Q, exd8=R
const PIECEMOVE = File_ChessPGN_Parser::PIECEMOVE; // Nf2, Nab2, N3d5, Qxe4, Qexe4, Q3xe4
const PLACEMENTMOVE = File_ChessPGN_Parser::PLACEMENTMOVE; // N@f2, P@d5
const CHECK = File_ChessPGN_Parser::CHECK; // +
const MATE = File_ChessPGN_Parser::MATE; // #
const DIGIT = File_ChessPGN_Parser::DIGIT; // 0-9
const MOVEANNOT = File_ChessPGN_Parser::MOVEANNOT; // ! ? !! ?? !? ?!
const RAVOPEN = File_ChessPGN_Parser::RAVOPEN; // (
const RAVCLOSE = File_ChessPGN_Parser::RAVCLOSE; // )
const PERIOD = File_ChessPGN_Parser::PERIOD; // .
const COMMENTOPEN = File_ChessPGN_Parser::COMMENTOPEN; // {
const COMMENTCLOSE = File_ChessPGN_Parser::COMMENTCLOSE; // }
const COMMENT = File_ChessPGN_Parser::COMMENT; // anything
const CASTLE = File_ChessPGN_Parser::CASTLE; // O-O O-O-O
private $input;
private $N;
public $token;
public $value;
public $line;
private $_string;
private $debug = 0;
function __construct($data)
{
$this->N = 0;
}
private $_yy_state = 1;
private $_yy_stack = array();
function yylex()
{
return $this->{'yylex' . $this->_yy_state}();
}
function yypushstate($state)
{
$this->_yy_state = $state;
}
function yypopstate()
{
$this->_yy_state =
array_pop($this->_yy_stack);
}
function yybegin($state)
{
$this->_yy_state = $state;
}
function yylex1()
{
$tokenMap = array (
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
);
if ($this->N >=
strlen($this->input)) {
return false; // end of input
}
$yy_global_pattern = "/^(\\[)|^(\\()|^((?:1-0|0-1|1\2-1\2))|^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)/";
do {
if (preg_match($yy_global_pattern, substr($this->input, $this->N), $yymatches)) {
$yysubmatches = $yymatches;
$yymatches =
array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
'an empty string. Input "' .
substr($this->input,
$this->N, 5) . '... state YYINITIAL');
}
next($yymatches); // skip global match
$this->token =
key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches =
array_slice($yysubmatches, $this->token +
1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value =
current($yymatches); // token value
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
if ($r === null) {
$this->N +=
strlen($this->value);
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->N +=
strlen($this->value);
if ($this->N >=
strlen($this->input)) {
return false; // end of input
}
// skip this token
continue;
} else { $yy_yymore_patterns = array(
1 => "^(\\()|^((?:1-0|0-1|1\2-1\2))|^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
2 => "^((?:1-0|0-1|1\2-1\2))|^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
3 => "^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
4 => "^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
5 => "^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
6 => "^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
7 => "^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)",
8 => "^(O-O-O|O-O)|^([ \n\t]+)",
9 => "^([ \n\t]+)",
10 => "",
);
// yymore is needed
do {
if (!strlen($yy_yymore_patterns[$this->token])) {
throw new Exception('cannot do yymore for the last token');
}
substr($this->input, $this->N), $yymatches)) {
$yymatches =
array_filter($yymatches, 'strlen'); // remove empty sub-patterns
next($yymatches); // skip global match
$this->token =
key($yymatches); // token number
$this->value =
current($yymatches); // token value
}
} while ($this->{'yy_r1_' . $this->token}() !== null);
// accept
$this->N +=
strlen($this->value);
return true;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->input[$this->N]);
}
break;
} while (true);
} // end function
const YYINITIAL = 1;
function yy_r1_1($yy_subpatterns)
{
if ($this->debug) echo 'new tag ['.$this->value."]\n";
$this->token = self::TAGOPEN;
$this->yybegin(self::INTAG);
}
function yy_r1_2($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo '->found rav ['.$this->value."]\n";
$this->token = self::RAVOPEN;
}
function yy_r1_3($yy_subpatterns)
{
// end of game
if ($this->debug) echo 'found game end ['.$this->value."]\n";
$this->token = self::GAMEEND;
}
function yy_r1_4($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo '->found digit ['.$this->value."]\n";
$this->token = self::DIGIT;
}
function yy_r1_5($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo '->found pawn move ['.$this->value."]\n";
$this->token = self::PAWNMOVE;
}
function yy_r1_6($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo '->found piece move ['.$this->value."]\n";
$this->token = self::PIECEMOVE;
}
function yy_r1_7($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo '->found placement move ['.$this->value."]\n";
$this->token = self::PLACEMENTMOVE;
}
function yy_r1_8($yy_subpatterns)
{
if ($this->debug) echo 'new comment ['.$this->value."]\n";
$this->yypushstate(self::INCOMMENT);
$this->token = self::COMMENTOPEN;
}
function yy_r1_9($yy_subpatterns)
{
$this->yybegin(self::INMOVES);
if ($this->debug) echo 'found castle move ['.$this->value."]\n";
$this->token = self::CASTLE;
}
function yy_r1_10($yy_subpatterns)
{
// cycle to next token
return false;
}
function yylex2()
{
$tokenMap = array (
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
14 => 0,
15 => 0,
16 => 0,
);
if ($this->N >=
strlen($this->input)) {
return false; // end of input
}
$yy_global_pattern = "/^(\\()|^((?:1-0|0-1|1\2-1\2))|^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))/";
do {
if (preg_match($yy_global_pattern, substr($this->input, $this->N), $yymatches)) {
$yysubmatches = $yymatches;
$yymatches =
array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
'an empty string. Input "' .
substr($this->input,
$this->N, 5) . '... state INMOVES');
}
next($yymatches); // skip global match
$this->token =
key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches =
array_slice($yysubmatches, $this->token +
1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value =
current($yymatches); // token value
$r = $this->{'yy_r2_' . $this->token}($yysubmatches);
if ($r === null) {
$this->N +=
strlen($this->value);
// accept this token
return true;
} elseif ($r === true) {
// we have changed state
// process this token in the new state
return $this->yylex();
} elseif ($r === false) {
$this->N +=
strlen($this->value);
if ($this->N >=
strlen($this->input)) {
return false; // end of input
}
// skip this token
continue;
} else { $yy_yymore_patterns = array(
1 => "^((?:1-0|0-1|1\2-1\2))|^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
2 => "^([0-9]{1,3})|^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
3 => "^(P?[a-h](?:[2-7]|[18]=(?:Q|R|B|N))|P?[a-h]x[a-h](?:[2-7]|[18]=(?:Q|R|B|N)))|^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
4 => "^((?:Q|K|R|B|N)(?:[a-h]|[1-8])?[a-h][1-8]|(?:Q|K|R|B|N)(?:[a-h]|[1-8])?x[a-h][1-8])|^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
5 => "^((?:P|K|Q|R|B|N)@[a-h][1-8])|^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
6 => "^(\\{)|^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
7 => "^(O-O-O|O-O)|^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
8 => "^([ \n\t]+)|^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
9 => "^(\\$[0-9]+)|^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
10 => "^(\\*)|^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
11 => "^(\\.)|^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
12 => "^(\\+)|^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
13 => "^(#)|^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
14 => "^(!|\\?|!!|\\?\\?|!\\?|\\?!)|^(\\))",
15 => "^(\\))",
16 => "",
);
// yymore is needed
do {
if (!strlen($yy_yymore_patterns[$this->token])) {
throw new Exception('cannot do yymore for the last token');
}
substr($this->input, $this->N), $yymatches)) {
$yymatches =
array_filter($yymatches, 'strlen'); // remove empty sub-patterns
next($yymatches); // skip global match
$this->token =
key($yymatches); // token number
$this->value =
current($yymatches); // token value
}
} while ($this->{'yy_r2_' . $this->token}() !== null);
// accept
$this->N +=
strlen($this->value);
return true;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->input[$this->N]);
}
break;
} while (true);
} // end function
const INMOVES = 2;
function yy_r2_1($yy_subpatterns)
{
if ($this->debug) echo '->found rav ['.$this->value."]\n";
$this->token = self::RAVOPEN;
}
function yy_r2_2($yy_subpatterns)
{
// end of game
$this->yybegin(self::YYINITIAL);
if ($this->debug) echo 'found game end ['.$this->value."]\n";
$this->token = self::GAMEEND;
}
function yy_r2_3($yy_subpatterns)
{
if ($this->debug) echo '->found digit ['.$this->value."]\n";
$this->token = self::DIGIT;
}
function yy_r2_4($yy_subpatterns)
{
if ($this->debug) echo '->found pawn move ['.$this->value."]\n";
$this->token = self::PAWNMOVE;
}
function yy_r2_5($yy_subpatterns)
{
if ($this->debug) echo '->found piece move ['.$this->value."]\n";
$this->token = self::PIECEMOVE;
}
function yy_r2_6($yy_subpatterns)
{
if ($this->debug) echo '->found placement move ['.$this->value."]\n";
$this->token = self::PLACEMENTMOVE;
}
function yy_r2_7($yy_subpatterns)
{
if ($this->debug) echo 'new comment ['.$this->value."]\n";
$this->yypushstate(self::INCOMMENT);
$this->token = self::COMMENTOPEN;
}
function yy_r2_8($yy_subpatterns)
{
if ($this->debug) echo 'found castle move ['.$this->value."]\n";
$this->token = self::CASTLE;
}
function yy_r2_9($yy_subpatterns)
{
// cycle to next token
return false;
}
function yy_r2_10($yy_subpatterns)
{
if ($this->debug) echo 'found numeric annotation glyph ['.$this->value."]\n";
$this->token = self::NAG;
}
function yy_r2_11($yy_subpatterns)
{