1 package Parsers::SimpleCalcParser; 2 # 3 # File: SimpleCalcParser.yy 4 # Author: Manish Sud <msud@san.rr.com> 5 # 6 # Copyright (C) 2022 Manish Sud. All rights reserved. 7 # 8 # This file is part of MayaChemTools. 9 # 10 # MayaChemTools is free software; you can redistribute it and/or modify it under 11 # the terms of the GNU Lesser General Public License as published by the Free 12 # Software Foundation; either version 3 of the License, or (at your option) any 13 # later version. 14 # 15 # MayaChemTools is distributed in the hope that it will be useful, but without 16 # any warranty; without even the implied warranty of merchantability of fitness 17 # for a particular purpose. See the GNU Lesser General Public License for more 18 # details. 19 # 20 # You should have received a copy of the GNU Lesser General Public License 21 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 22 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 23 # Boston, MA, 02111-1307, USA. 24 # 25 # 26 # A WORD TO THE WISE: 27 # 28 # The parser package and token table files, SimpleCalcParser.pm and 29 # SimpleCalcParser.tab.ph, are automatically generated from parser grammar 30 # definition file, SimpleCalcParser.yy, using byacc available through perl-byacc1.8 31 # modified with perl5-byacc-patches-0.5 for generation of object oriented parser: 32 # 33 # byacc -l -P -d -b SimpleCalcParser SimpleCalcParser.yy 34 # mv SimpleCalcParser.tab.pl SimpleCalcParser.pm 35 # 36 37 use Carp; 38 39 # Setup a hash map for mapping of words/letters to values... 40 %LetterToValueMap = (); 41 42 $NUMBER=257; 43 $LETTER=258; 44 $YYERRCODE=256; 45 @yylhs = ( -1, 46 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 47 2, 2, 2, 48 ); 49 @yylen = ( 2, 50 0, 3, 3, 1, 3, 3, 3, 3, 3, 3, 51 3, 1, 1, 52 ); 53 @yydefred = ( 1, 54 0, 0, 12, 0, 0, 0, 0, 3, 0, 13, 55 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 56 0, 0, 0, 11, 57 ); 58 @yydgoto = ( 1, 59 6, 7, 60 ); 61 @yysindex = ( 0, 62 -40, -7, 0, -57, -38, -5, -18, 0, -38, 0, 63 -31, 0, -38, -38, -38, -38, -38, -18, 0, -16, 64 -16, -30, -30, 0, 65 ); 66 @yyrindex = ( 0, 67 0, 0, 0, -9, 0, 0, -1, 0, 0, 0, 68 0, 0, 0, 0, 0, 0, 0, 3, 0, 8, 69 13, -2, 5, 0, 70 ); 71 @yygindex = ( 0, 72 0, 50, 73 ); 74 $YYTABLESIZE=220; 75 @yytable = ( 5, 76 13, 5, 8, 9, 12, 17, 17, 9, 4, 19, 77 15, 13, 5, 14, 10, 16, 0, 7, 17, 0, 78 17, 0, 8, 15, 13, 15, 14, 13, 16, 0, 79 16, 0, 13, 13, 0, 13, 0, 13, 9, 9, 80 9, 0, 9, 0, 9, 10, 10, 10, 7, 10, 81 7, 10, 7, 8, 11, 8, 0, 8, 18, 0, 82 0, 0, 20, 21, 22, 23, 24, 0, 0, 0, 83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97 0, 0, 0, 0, 0, 2, 3, 4, 3, 10, 98 ); 99 @yycheck = ( 40, 100 10, 40, 10, 61, 10, 37, 37, 10, 10, 41, 101 42, 43, 10, 45, 10, 47, -1, 10, 37, -1, 102 37, -1, 10, 42, 43, 42, 45, 37, 47, -1, 103 47, -1, 42, 43, -1, 45, -1, 47, 41, 42, 104 43, -1, 45, -1, 47, 41, 42, 43, 41, 45, 105 43, 47, 45, 41, 5, 43, -1, 45, 9, -1, 106 -1, -1, 13, 14, 15, 16, 17, -1, -1, -1, 107 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 110 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 111 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 112 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 113 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 114 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 115 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 117 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 118 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 119 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 120 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 121 -1, -1, -1, -1, -1, 256, 257, 258, 257, 258, 122 ); 123 $YYFINAL=1; 124 #ifndef YYDEBUG 125 #define YYDEBUG 0 126 #endif 127 $YYMAXTOKEN=258; 128 #if YYDEBUG 129 @yyname = ( 130 "end-of-file",'','','','','','','','','',"'\\n'",'','','','','','','','','','','','','','','','','','','','', 131 '','','','','','',"'%'",'','',"'('","')'","'*'","'+'",'',"'-'",'',"'/'",'','','','','','','','','', 132 '','','','',"'='",'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','', 133 '','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','', 134 '','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','', 135 '','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','', 136 '','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','', 137 '','',"NUMBER","LETTER", 138 ); 139 @yyrule = ( 140 "\$accept : list", 141 "list :", 142 "list : list stat '\\n'", 143 "list : list error '\\n'", 144 "stat : expr", 145 "stat : LETTER '=' expr", 146 "expr : '(' expr ')'", 147 "expr : expr '+' expr", 148 "expr : expr '-' expr", 149 "expr : expr '*' expr", 150 "expr : expr '/' expr", 151 "expr : expr '%' expr", 152 "expr : NUMBER", 153 "expr : LETTER", 154 ); 155 #endif 156 157 sub yyclearin { $_[0]->{'yychar'} = -1; } 158 159 sub yyerrok { $_[0]->{'yyerrflag'} = 0; } 160 161 sub new { 162 my $p = {'yylex' => $_[1], 'yyerror' => $_[2], 'yydebug' => $_[3]}; 163 bless $p, $_[0]; 164 } 165 166 sub YYERROR { ++$_[0]->{'yynerrs'}; $_[0]->yy_err_recover; } 167 168 sub yy_err_recover { 169 # 170 # msud@san.rr.com: 171 # 172 # Turn off "exiting" warning to suppress the following warning at "next yyloop": 173 # 174 # Exiting subroutine via next at <LineNum> 175 # 176 # The code does work as expected with or without turning off the warning. 177 # This method is invoked in yyparse method directly or indirectly in another 178 # method and Perl compilers ends up finding "yyloop" as the nearst enclosure 179 # label. 180 # 181 no warnings qw(exiting); 182 183 my ($p) = @_; 184 if ($p->{'yyerrflag'} < 3) 185 { 186 $p->{'yyerrflag'} = 3; 187 while (1) 188 { 189 if (($p->{'yyn'} = $yysindex[$p->{'yyss'}->[$p->{'yyssp'}]]) && 190 ($p->{'yyn'} += $YYERRCODE) >= 0 && 191 $p->{'yyn'} < @yycheck && 192 $yycheck[$p->{'yyn'}] == $YYERRCODE) 193 { 194 warn("yydebug: state " . 195 $p->{'yyss'}->[$p->{'yyssp'}] . 196 ", error recovery shifting to state" . 197 $yytable[$p->{'yyn'}] . "\n") 198 if $p->{'yydebug'}; 199 $p->{'yyss'}->[++$p->{'yyssp'}] = 200 $p->{'yystate'} = $yytable[$p->{'yyn'}]; 201 $p->{'yyvs'}->[++$p->{'yyvsp'}] = $p->{'yylval'}; 202 next yyloop; 203 } 204 else 205 { 206 warn("yydebug: error recovery discarding state ". 207 $p->{'yyss'}->[$p->{'yyssp'}]. "\n") 208 if $p->{'yydebug'}; 209 return(undef) if $p->{'yyssp'} <= 0; 210 --$p->{'yyssp'}; 211 --$p->{'yyvsp'}; 212 } 213 } 214 } 215 else 216 { 217 return (undef) if $p->{'yychar'} == 0; 218 if ($p->{'yydebug'}) 219 { 220 $p->{'yys'} = ''; 221 if ($p->{'yychar'} <= $YYMAXTOKEN) { $p->{'yys'} = 222 $yyname[$p->{'yychar'}]; } 223 if (!$p->{'yys'}) { $p->{'yys'} = 'illegal-symbol'; } 224 warn("yydebug: state " . $p->{'yystate'} . 225 ", error recovery discards " . 226 "token " . $p->{'yychar'} . "(" . 227 $p->{'yys'} . ")\n"); 228 } 229 $p->{'yychar'} = -1; 230 next yyloop; 231 } 232 0; 233 } # yy_err_recover 234 235 sub yyparse { 236 my ($p, $s) = @_; 237 if ($p->{'yys'} = $ENV{'YYDEBUG'}) 238 { 239 $p->{'yydebug'} = int($1) if $p->{'yys'} =~ /^(\d)/; 240 } 241 242 $p->{'yynerrs'} = 0; 243 $p->{'yyerrflag'} = 0; 244 $p->{'yychar'} = (-1); 245 246 $p->{'yyssp'} = 0; 247 $p->{'yyvsp'} = 0; 248 $p->{'yyss'}->[$p->{'yyssp'}] = $p->{'yystate'} = 0; 249 250 yyloop: while(1) 251 { 252 yyreduce: { 253 last yyreduce if ($p->{'yyn'} = $yydefred[$p->{'yystate'}]); 254 if ($p->{'yychar'} < 0) 255 { 256 if ((($p->{'yychar'}, $p->{'yylval'}) = 257 &{$p->{'yylex'}}($s)) < 0) { $p->{'yychar'} = 0; } 258 if ($p->{'yydebug'}) 259 { 260 $p->{'yys'} = ''; 261 if ($p->{'yychar'} <= $#yyname) 262 { $p->{'yys'} = $yyname[$p->{'yychar'}]; } 263 if (!$p->{'yys'}) { $p->{'yys'} = 'illegal-symbol'; }; 264 warn("yydebug: state " . $p->{'yystate'} . 265 ", reading " . $p->{'yychar'} . " (" . 266 $p->{'yys'} . ")\n"); 267 } 268 } 269 if (($p->{'yyn'} = $yysindex[$p->{'yystate'}]) && 270 ($p->{'yyn'} += $p->{'yychar'}) >= 0 && 271 $yycheck[$p->{'yyn'}] == $p->{'yychar'}) 272 { 273 warn("yydebug: state " . $p->{'yystate'} . 274 ", shifting to state " . 275 $yytable[$p->{'yyn'}] . "\n") if $p->{'yydebug'}; 276 $p->{'yyss'}->[++$p->{'yyssp'}] = $p->{'yystate'} = 277 $yytable[$p->{'yyn'}]; 278 $p->{'yyvs'}->[++$p->{'yyvsp'}] = $p->{'yylval'}; 279 $p->{'yychar'} = (-1); 280 --$p->{'yyerrflag'} if $p->{'yyerrflag'} > 0; 281 next yyloop; 282 } 283 if (($p->{'yyn'} = $yyrindex[$p->{'yystate'}]) && 284 ($p->{'yyn'} += $p->{'yychar'}) >= 0 && 285 $yycheck[$p->{'yyn'}] == $p->{'yychar'}) 286 { 287 $p->{'yyn'} = $yytable[$p->{'yyn'}]; 288 last yyreduce; 289 } 290 if (! $p->{'yyerrflag'}) { 291 if ( (defined($EOI) && $p->{'yychar'} == $EOI) || ($p->{'yychar'} == 0) ) { 292 &{$p->{'yyerror'}}("syntax error at or near the end of input text", $s); 293 } 294 else { 295 &{$p->{'yyerror'}}("syntax error at or near input text: '$p->{'yylval'}'", $s); 296 } 297 ++$p->{'yynerrs'}; 298 } 299 return(undef) if $p->yy_err_recover; 300 } # yyreduce 301 warn("yydebug: state " . $p->{'yystate'} . 302 ", reducing by rule " . 303 $p->{'yyn'} . " (" . $yyrule[$p->{'yyn'}] . 304 ")\n") if $p->{'yydebug'}; 305 $p->{'yym'} = $yylen[$p->{'yyn'}]; 306 $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}+1-$p->{'yym'}]; 307 308 if ($p->{'yyn'} == 2) { 309 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-1]; } 310 } 311 312 if ($p->{'yyn'} == 3) { 313 { $p->yyerrok; $p->yyclearin; } 314 } 315 316 if ($p->{'yyn'} == 4) { 317 { $ExprOut = sprintf "%5i", $p->{'yyvs'}->[$p->{'yyvsp'}-0]; print "$ExprOut\n"; $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 318 } 319 320 if ($p->{'yyn'} == 5) { 321 { $LetterToValueMap{$p->{'yyvs'}->[$p->{'yyvsp'}-2]} = $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 322 } 323 324 if ($p->{'yyn'} == 6) { 325 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-1]; } 326 } 327 328 if ($p->{'yyn'} == 7) { 329 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-2] + $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 330 } 331 332 if ($p->{'yyn'} == 8) { 333 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-2] - $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 334 } 335 336 if ($p->{'yyn'} == 9) { 337 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-2] * $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 338 } 339 340 if ($p->{'yyn'} == 10) { 341 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-2] / $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 342 } 343 344 if ($p->{'yyn'} == 11) { 345 { $p->{'yyval'} = $p->{'yyvs'}->[$p->{'yyvsp'}-2] % $p->{'yyvs'}->[$p->{'yyvsp'}-0]; } 346 } 347 348 if ($p->{'yyn'} == 13) { 349 { 350 if (exists $LetterToValueMap{$p->{'yyvs'}->[$p->{'yyvsp'}-0]}) { 351 $p->{'yyval'} = $LetterToValueMap{$p->{'yyvs'}->[$p->{'yyvsp'}-0]}; 352 } 353 else { 354 $Letter = $p->{'yyvs'}->[$p->{'yyvsp'}-0]; 355 print "Undefined variable $Letter encountered by SimpleCalcParser; Value set to 0\n"; 356 $p->{'yyval'} = 0; 357 } 358 } 359 } 360 $p->{'yyssp'} -= $p->{'yym'}; 361 $p->{'yystate'} = $p->{'yyss'}->[$p->{'yyssp'}]; 362 $p->{'yyvsp'} -= $p->{'yym'}; 363 $p->{'yym'} = $yylhs[$p->{'yyn'}]; 364 if ($p->{'yystate'} == 0 && $p->{'yym'} == 0) 365 { 366 warn("yydebug: after reduction, shifting from state 0 ", 367 "to state $YYFINAL\n") if $p->{'yydebug'}; 368 $p->{'yystate'} = $YYFINAL; 369 $p->{'yyss'}->[++$p->{'yyssp'}] = $YYFINAL; 370 $p->{'yyvs'}->[++$p->{'yyvsp'}] = $p->{'yyval'}; 371 if ($p->{'yychar'} < 0) 372 { 373 if ((($p->{'yychar'}, $p->{'yylval'}) = 374 &{$p->{'yylex'}}($s)) < 0) { $p->{'yychar'} = 0; } 375 if ($p->{'yydebug'}) 376 { 377 $p->{'yys'} = ''; 378 if ($p->{'yychar'} <= $#yyname) 379 { $p->{'yys'} = $yyname[$p->{'yychar'}]; } 380 if (!$p->{'yys'}) { $p->{'yys'} = 'illegal-symbol'; } 381 warn("yydebug: state $YYFINAL, reading " . 382 $p->{'yychar'} . " (" . $p->{'yys'} . ")\n"); 383 } 384 } 385 return ($p->{'yyvs'}->[1]) if $p->{'yychar'} == 0; 386 next yyloop; 387 } 388 if (($p->{'yyn'} = $yygindex[$p->{'yym'}]) && 389 ($p->{'yyn'} += $p->{'yystate'}) >= 0 && 390 $p->{'yyn'} <= $#yycheck && 391 $yycheck[$p->{'yyn'}] == $p->{'yystate'}) 392 { 393 $p->{'yystate'} = $yytable[$p->{'yyn'}]; 394 } else { 395 $p->{'yystate'} = $yydgoto[$p->{'yym'}]; 396 } 397 warn("yydebug: after reduction, shifting from state " . 398 $p->{'yyss'}->[$p->{'yyssp'}] . " to state " . 399 $p->{'yystate'} . "\n") if $p->{'yydebug'}; 400 $p->{'yyss'}[++$p->{'yyssp'}] = $p->{'yystate'}; 401 $p->{'yyvs'}[++$p->{'yyvsp'}] = $p->{'yyval'}; 402 } # yyloop 403 } # yyparse 404 405 406 # yyerror function supplied to parser along with a lexer during initialization of 407 # the parser... 408 # 409 410 sub yyerror { 411 my ($msg) = @_; 412 print "yyerror: $msg...\n"; 413 } 414