Home | History | Annotate | Download | only in tests
      1 # Java tests for simple calculator.           -*- Autotest -*-
      2 
      3 # Copyright (C) 2007-2012 Free Software Foundation, Inc.
      4 
      5 # This program is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU General Public License as published by
      7 # the Free Software Foundation, either version 3 of the License, or
      8 # (at your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 AT_BANNER([[Java Calculator.]])
     19 
     20 
     21 # ------------------------- #
     22 # Helping Autotest macros.  #
     23 # ------------------------- #
     24 
     25 
     26 # _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
     27 # ----------------------------------------------------------------------
     28 # Produce `calc.y'.  Don't call this macro directly, because it contains
     29 # some occurrences of `$1' etc. which will be interpreted by m4.  So
     30 # you should call it with $1, $2, and $3 as arguments, which is what
     31 # AT_DATA_JAVA_CALC_Y does.
     32 m4_define([_AT_DATA_JAVA_CALC_Y],
     33 [m4_if([$1$2$3], $[1]$[2]$[3], [],
     34        [m4_fatal([$0: Invalid arguments: $@])])dnl
     35 AT_BISON_OPTION_PUSHDEFS([%language "Java" $4])
     36 AT_DATA([Calc.y],
     37 [[/* Infix notation calculator--calc */
     38 %language "Java"
     39 %name-prefix "Calc"
     40 %define parser_class_name "Calc"
     41 %define public
     42 
     43 ]$4[
     44 
     45 %code imports {
     46   import java.io.StreamTokenizer;
     47   import java.io.InputStream;
     48   import java.io.InputStreamReader;
     49   import java.io.Reader;
     50   import java.io.IOException;
     51 }
     52 
     53 /* Bison Declarations */
     54 %token <Integer> NUM "number"
     55 %type  <Integer> exp
     56 
     57 %nonassoc '=' /* comparison            */
     58 %left '-' '+'
     59 %left '*' '/'
     60 %left NEG     /* negation--unary minus */
     61 %right '^'    /* exponentiation        */
     62 
     63 /* Grammar follows */
     64 %%
     65 input:
     66   line
     67 | input line
     68 ;
     69 
     70 line:
     71   '\n'
     72 | exp '\n'
     73 | error '\n'
     74 ;
     75 
     76 exp:
     77   NUM                { $$ = $1;                                             }
     78 | exp '=' exp
     79   {
     80     if ($1.intValue () != $3.intValue ())
     81       yyerror (]AT_LOCATION_IF([[@$,]])[ "calc: error: " + $1 + " != " + $3);
     82   }
     83 | exp '+' exp        { $$ = new Integer ($1.intValue () + $3.intValue ());  }
     84 | exp '-' exp        { $$ = new Integer ($1.intValue () - $3.intValue ());  }
     85 | exp '*' exp        { $$ = new Integer ($1.intValue () * $3.intValue ());  }
     86 | exp '/' exp        { $$ = new Integer ($1.intValue () / $3.intValue ());  }
     87 | '-' exp  %prec NEG { $$ = new Integer (-$2.intValue ());                  }
     88 | exp '^' exp        { $$ = new Integer ((int)
     89                                          Math.pow ($1.intValue (),
     90                                                    $3.intValue ()));        }
     91 | '(' exp ')'        { $$ = $2;                                             }
     92 | '(' error ')'      { $$ = new Integer (1111);                             }
     93 | '!'                { $$ = new Integer (0); return YYERROR;                }
     94 | '-' error          { $$ = new Integer (0); return YYERROR;                }
     95 ;
     96 
     97 ]AT_LEXPARAM_IF([[
     98 %code lexer {
     99 ]],
    100 [[
    101 %%
    102 class CalcLexer implements Calc.Lexer {
    103 ]])[
    104   StreamTokenizer st;
    105 
    106   public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]]) (InputStream is)
    107   {
    108     st = new StreamTokenizer (new InputStreamReader (is));
    109     st.resetSyntax ();
    110     st.eolIsSignificant (true);
    111     st.whitespaceChars (9, 9);
    112     st.whitespaceChars (32, 32);
    113     st.wordChars (48, 57);
    114   }
    115 
    116 AT_LOCATION_IF([[
    117   Position yypos = new Position (1, 0);
    118 
    119   public Position getStartPos() {
    120     return yypos;
    121   }
    122 
    123   public Position getEndPos() {
    124     return yypos;
    125   }
    126 ]])[
    127   ]AT_YYERROR_DEFINE[
    128 
    129   Integer yylval;
    130 
    131   public Object getLVal() {
    132     return yylval;
    133   }
    134 
    135   public int yylex () throws IOException {
    136     int ttype = st.nextToken ();
    137     ]AT_LOCATION_IF([[yypos = new Position (yypos.lineno (),
    138                                             yypos.token () + 1);]])[
    139     if (ttype == st.TT_EOF)
    140       return Calc.EOF;
    141 
    142     else if (ttype == st.TT_EOL)
    143       {
    144         ]AT_LOCATION_IF([[yypos = new Position (yypos.lineno () + 1, 0);]])[
    145         return (int) '\n';
    146       }
    147 
    148     else if (ttype == st.TT_WORD)
    149       {
    150         yylval = new Integer (st.sval);
    151         return Calc.NUM;
    152       }
    153 
    154     else
    155       return st.ttype;
    156   }
    157 
    158 
    159 ]AT_LEXPARAM_IF([[
    160 };
    161 %%]], [[
    162 }]])
    163 
    164 [
    165 class Position {
    166   public int line;
    167   public int token;
    168 
    169   public Position ()
    170   {
    171     line = 0;
    172     token = 0;
    173   }
    174 
    175   public Position (int l, int t)
    176   {
    177     line = l;
    178     token = t;
    179   }
    180 
    181   public boolean equals (Position l)
    182   {
    183     return l.line == line && l.token == token;
    184   }
    185 
    186   public String toString ()
    187   {
    188     return Integer.toString (line) + "." + Integer.toString(token);
    189   }
    190 
    191   public int lineno ()
    192   {
    193     return line;
    194   }
    195 
    196   public int token ()
    197   {
    198     return token;
    199   }
    200 }
    201 
    202 ]])
    203 AT_BISON_OPTION_POPDEFS
    204 ])# _AT_DATA_JAVA_CALC_Y
    205 
    206 
    207 # AT_DATA_CALC_Y([BISON-OPTIONS])
    208 # -------------------------------
    209 # Produce `calc.y'.
    210 m4_define([AT_DATA_JAVA_CALC_Y],
    211 [_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1])
    212 ])
    213 
    214 
    215 # _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT,
    216 #                           [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
    217 # --------------------------------------------------------------
    218 # Run `calc' on INPUT, and expect a `syntax error' message.
    219 #
    220 # If INPUT starts with a slash, it is used as absolute input file name,
    221 # otherwise as contents.
    222 #
    223 # The VERBOSE-AND-LOCATED-ERROR-MESSAGE is stripped of locations
    224 # and expected tokens if necessary, and compared with the output.
    225 m4_define([_AT_CHECK_JAVA_CALC_ERROR],
    226 [m4_bmatch([$2], [^/],
    227            [AT_JAVA_PARSER_CHECK([Calc < $2], 0, [], [stderr])],
    228            [AT_DATA([[input]],
    229 [[$2
    230 ]])
    231 AT_JAVA_PARSER_CHECK([Calc < input], 0, [], [stderr])])
    232 
    233 # Normalize the observed and expected error messages, depending upon the
    234 # options.
    235 # 1. Create the reference error message.
    236 AT_DATA([[expout]],
    237 [$3
    238 ])
    239 # 2. If locations are not used, remove them.
    240 AT_YYERROR_SEES_LOC_IF([],
    241 [[sed 's/^[-0-9.]*: //' expout >at-expout
    242 mv at-expout expout]])
    243 # 3. If error-verbose is not used, strip the`, unexpected....' part.
    244 m4_bmatch([$1], [%error-verbose], [],
    245 [[sed 's/syntax error, .*$/syntax error/' expout >at-expout
    246 mv at-expout expout]])
    247 # 4. Check
    248 AT_CHECK([cat stderr], 0, [expout])
    249 ])
    250 
    251 # _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE])
    252 # -----------------------------------------------------------------------
    253 # Start a testing chunk which compiles `calc' grammar with
    254 # BISON-DIRECTIVES, and performs several tests over the parser.
    255 m4_define([_AT_CHECK_JAVA_CALC],
    256 [# We use integers to avoid dependencies upon the precision of doubles.
    257 AT_SETUP([Calculator $1])
    258 
    259 AT_BISON_OPTION_PUSHDEFS([$1])
    260 
    261 AT_DATA_JAVA_CALC_Y([$1
    262 %code {
    263 $2
    264 }])
    265 
    266 AT_BISON_CHECK([-o Calc.java Calc.y])
    267 AT_JAVA_COMPILE([Calc.java])
    268 
    269 # Test the priorities.
    270 AT_DATA([[input]],
    271 [[1 + 2 * 3 = 7
    272 1 + 2 * -3 = -5
    273 
    274 -1^2 = -1
    275 (-1)^2 = 1
    276 
    277 ---1 = -1
    278 
    279 1 - 2 - 3 = -4
    280 1 - (2 - 3) = 2
    281 
    282 2^2^3 = 256
    283 (2^2)^3 = 64
    284 ]])
    285 AT_JAVA_PARSER_CHECK([Calc < input], 0, [], [stderr])
    286 
    287 
    288 # Some syntax errors.
    289 _AT_CHECK_JAVA_CALC_ERROR([$1], [0 0],
    290                           [1.2: syntax error, unexpected number])
    291 _AT_CHECK_JAVA_CALC_ERROR([$1], [1//2],
    292                           [1.3: syntax error, unexpected '/', expecting number or '-' or '(' or '!'])
    293 _AT_CHECK_JAVA_CALC_ERROR([$1], [error],
    294                           [1.1: syntax error, unexpected $undefined])
    295 _AT_CHECK_JAVA_CALC_ERROR([$1], [1 = 2 = 3],
    296                           [1.4: syntax error, unexpected '='])
    297 _AT_CHECK_JAVA_CALC_ERROR([$1], [
    298 +1],
    299                           [2.1: syntax error, unexpected '+'])
    300 # Exercise error messages with EOF: work on an empty file.
    301 _AT_CHECK_JAVA_CALC_ERROR([$1], [/dev/null],
    302                           [1.1: syntax error, unexpected end of input])
    303 
    304 # Exercise the error token: without it, we die at the first error,
    305 # hence be sure to
    306 #
    307 # - have several errors which exercise different shift/discardings
    308 #   - (): nothing to pop, nothing to discard
    309 #   - (1 + 1 + 1 +): a lot to pop, nothing to discard
    310 #   - (* * *): nothing to pop, a lot to discard
    311 #   - (1 + 2 * *): some to pop and discard
    312 #
    313 # - test the action associated to `error'
    314 #
    315 # - check the lookahead that triggers an error is not discarded
    316 #   when we enter error recovery.  Below, the lookahead causing the
    317 #   first error is ")", which is needed to recover from the error and
    318 #   produce the "0" that triggers the "0 != 1" error.
    319 #
    320 _AT_CHECK_JAVA_CALC_ERROR([$1],
    321                           [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
    322 [1.2: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
    323 1.11: syntax error, unexpected ')', expecting number or '-' or '(' or '!'
    324 1.14: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
    325 1.24: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
    326 1.1-1.27: calc: error: 4444 != 1])
    327 
    328 # The same, but this time exercising explicitly triggered syntax errors.
    329 # POSIX says the lookahead causing the error should not be discarded.
    330 _AT_CHECK_JAVA_CALC_ERROR([$1], [(!) + (0 0) = 1],
    331 [1.7: syntax error, unexpected number
    332 1.1-1.10: calc: error: 2222 != 1])
    333 _AT_CHECK_JAVA_CALC_ERROR([$1], [(- *) + (0 0) = 1],
    334 [1.3: syntax error, unexpected '*', expecting number or '-' or '(' or '!'
    335 1.8: syntax error, unexpected number
    336 1.1-1.11: calc: error: 2222 != 1])
    337 AT_BISON_OPTION_POPDEFS
    338 
    339 AT_CLEANUP
    340 ])# _AT_CHECK_JAVA_CALC
    341 
    342 
    343 # AT_CHECK_JAVA_CALC([BISON-DIRECTIVES])
    344 # --------------------------------------------------------
    345 # Start a testing chunk which compiles `calc' grammar with
    346 # BISON-DIRECTIVES, and performs several tests over the parser.
    347 # Run the test with and without %error-verbose.
    348 m4_define([AT_CHECK_JAVA_CALC],
    349 [_AT_CHECK_JAVA_CALC([$1], [$2])
    350 _AT_CHECK_JAVA_CALC([%error-verbose $1], [$2])
    351 _AT_CHECK_JAVA_CALC([%locations $1], [$2])
    352 _AT_CHECK_JAVA_CALC([%error-verbose %locations $1], [$2])
    353 ])# AT_CHECK_JAVA_CALC
    354 
    355 
    356 # ------------------------ #
    357 # Simple LALR Calculator.  #
    358 # ------------------------ #
    359 
    360 AT_CHECK_JAVA_CALC([], [[
    361   public static void main (String args[]) throws IOException
    362   {
    363     CalcLexer l = new CalcLexer (System.in);
    364     Calc p = new Calc (l);
    365     p.parse ();
    366   }
    367 ]])
    368 
    369 AT_CHECK_JAVA_CALC([%lex-param { InputStream is } ], [[
    370   public static void main (String args[]) throws IOException
    371   {
    372     new Calc (System.in).parse ();
    373   }
    374 ]])
    375 
    376 
    377 
    378 # -----------------#
    379 # Java Directives. #
    380 # -----------------#
    381 
    382 AT_BANNER([Java Parameters.])
    383 
    384 
    385 # AT_CHECK_JAVA_MINIMAL([DIRECTIVES], [PARSER_ACTION], [POSITION_CLASS])
    386 # ----------------------------------------------------------------------
    387 # Check that a mininal parser with DIRECTIVES compiles in Java.
    388 # Put the Java code in YYParser.java.
    389 m4_define([AT_CHECK_JAVA_MINIMAL],
    390 [
    391 AT_DATA([[YYParser.y]], [
    392 %language "Java"
    393 %locations
    394 %debug
    395 %error-verbose
    396 %token-table
    397 $1
    398 %%
    399 start: "end" {$2};
    400 %%
    401 class m4_default([$3], [Position]) {}
    402 ])
    403 AT_BISON_CHECK([[YYParser.y]])
    404 AT_CHECK([[grep '[mb]4_' YYParser.y]], [1], [ignore])
    405 AT_JAVA_COMPILE([[YYParser.java]])
    406 ])
    407 
    408 
    409 # AT_CHECK_JAVA_MINIMAL_W_LEXER([1:DIRECTIVES], [2:LEX_THROWS],
    410 #       [3:YYLEX_ACTION], [4:LEXER_BODY], [5:PARSER_ACTION], [6:STYPE],
    411 #       [7:POSITION_TYPE], [8:LOCATION_TYPE])
    412 # ---------------------------------------------------------------------
    413 # Check that a mininal parser with DIRECTIVES and a "%code lexer".
    414 # YYLEX is the body of yylex () which throws LEX_THROW.
    415 # compiles in Java.
    416 m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
    417 [AT_CHECK_JAVA_MINIMAL([$1
    418 
    419 %code lexer
    420 {
    421   m4_default([$6], [Object]) yylval;
    422   public m4_default([$6], [Object]) getLVal() { return yylval; }
    423 
    424   public m4_default([$7], [Position]) getStartPos() { return null; }
    425   public m4_default([$7], [Position]) getEndPos()   { return null; }
    426 
    427   public void yyerror (m4_default([$8], [Location]) loc, String s)
    428   {
    429     System.err.println (loc + ": " + s);
    430   }
    431 
    432   public int yylex ()$2
    433   {
    434     $3
    435   }
    436 
    437   $4
    438 }], [$5], [$7])])
    439 
    440 
    441 # AT_CHECK_JAVA_GREP([LINE], [COUNT=1])
    442 # -------------------------------------
    443 # Check that YYParser.java contains exactly COUNT lines matching ^LINE$
    444 # with grep.
    445 m4_define([AT_CHECK_JAVA_GREP],
    446 	[AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
    447 ])
    448 ])
    449 
    450 
    451 # ----------------------------------- #
    452 # Java parser class and package names #
    453 # ----------------------------------- #
    454 
    455 AT_SETUP([Java parser class and package names])
    456 
    457 AT_CHECK_JAVA_MINIMAL([])
    458 AT_CHECK_JAVA_GREP([[class YYParser]])
    459 
    460 AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
    461 AT_CHECK_JAVA_GREP([[class PrefixParser]])
    462 
    463 AT_CHECK_JAVA_MINIMAL([[%define parser_class_name "ParserClassName"]])
    464 AT_CHECK_JAVA_GREP([[class ParserClassName]])
    465 
    466 AT_CHECK_JAVA_MINIMAL([[%define package "user_java_package"]])
    467 AT_CHECK_JAVA_GREP([[package user_java_package;]])
    468 
    469 AT_CLEANUP
    470 
    471 
    472 # --------------------------- #
    473 # Java parser class modifiers #
    474 # --------------------------- #
    475 
    476 AT_SETUP([Java parser class modifiers])
    477 
    478 AT_CHECK_JAVA_MINIMAL([[%define abstract]])
    479 AT_CHECK_JAVA_GREP([[abstract class YYParser]])
    480 
    481 AT_CHECK_JAVA_MINIMAL([[%define final]])
    482 AT_CHECK_JAVA_GREP([[final class YYParser]])
    483 
    484 AT_CHECK_JAVA_MINIMAL([[%define strictfp]])
    485 AT_CHECK_JAVA_GREP([[strictfp class YYParser]])
    486 
    487 AT_CHECK_JAVA_MINIMAL([[
    488 %define abstract
    489 %define strictfp]])
    490 AT_CHECK_JAVA_GREP([[abstract strictfp class YYParser]])
    491 
    492 AT_CHECK_JAVA_MINIMAL([[
    493 %define final
    494 %define strictfp]])
    495 AT_CHECK_JAVA_GREP([[final strictfp class YYParser]])
    496 
    497 AT_CHECK_JAVA_MINIMAL([[%define public]])
    498 AT_CHECK_JAVA_GREP([[public class YYParser]])
    499 
    500 AT_CHECK_JAVA_MINIMAL([[
    501 %define public
    502 %define abstract]])
    503 AT_CHECK_JAVA_GREP([[public abstract class YYParser]])
    504 
    505 AT_CHECK_JAVA_MINIMAL([[
    506 %define public
    507 %define final]])
    508 AT_CHECK_JAVA_GREP([[public final class YYParser]])
    509 
    510 AT_CHECK_JAVA_MINIMAL([[
    511 %define public
    512 %define strictfp]])
    513 AT_CHECK_JAVA_GREP([[public strictfp class YYParser]])
    514 
    515 AT_CHECK_JAVA_MINIMAL([[
    516 %define public
    517 %define abstract
    518 %define strictfp]])
    519 AT_CHECK_JAVA_GREP([[public abstract strictfp class YYParser]])
    520 
    521 AT_CHECK_JAVA_MINIMAL([[
    522 %define public
    523 %define final
    524 %define strictfp]])
    525 AT_CHECK_JAVA_GREP([[public final strictfp class YYParser]])
    526 
    527 AT_CLEANUP
    528 
    529 
    530 # ---------------------------------------- #
    531 # Java parser class extends and implements #
    532 # ---------------------------------------- #
    533 
    534 AT_SETUP([Java parser class extends and implements])
    535 
    536 AT_CHECK_JAVA_MINIMAL([[%define extends "Thread"]])
    537 AT_CHECK_JAVA_GREP([[class YYParser extends Thread]])
    538 
    539 AT_CHECK_JAVA_MINIMAL([[%define implements "Cloneable"]])
    540 AT_CHECK_JAVA_GREP([[class YYParser implements Cloneable]])
    541 
    542 AT_CHECK_JAVA_MINIMAL([[
    543 %define extends "Thread"
    544 %define implements "Cloneable"]])
    545 AT_CHECK_JAVA_GREP([[class YYParser extends Thread implements Cloneable]])
    546 
    547 AT_CLEANUP
    548 
    549 
    550 # -------------------------------- #
    551 # Java %parse-param and %lex-param #
    552 # -------------------------------- #
    553 
    554 AT_SETUP([Java %parse-param and %lex-param])
    555 
    556 AT_CHECK_JAVA_MINIMAL([])
    557 AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer) {]])
    558 
    559 AT_CHECK_JAVA_MINIMAL([[%parse-param {int parse_param1}]])
    560 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
    561 AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1) {]])
    562 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param1 = parse_param1;]])
    563 
    564 AT_CHECK_JAVA_MINIMAL([[
    565 %parse-param {int parse_param1}
    566 %parse-param {long parse_param2}]])
    567 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
    568 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
    569 AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
    570 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param1 = parse_param1;]])
    571 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param2 = parse_param2;]])
    572 
    573 AT_CHECK_JAVA_MINIMAL_W_LEXER([], [], [[return EOF;]])
    574 AT_CHECK_JAVA_GREP([[ *public YYParser () {]])
    575 AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer) {]])
    576 
    577 AT_CHECK_JAVA_MINIMAL_W_LEXER([[%parse-param {int parse_param1}]],
    578 	[], [[return EOF;]])
    579 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
    580 AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1) {]])
    581 AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1) {]])
    582 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param1 = parse_param1;]], [2])
    583 
    584 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
    585 %parse-param {int parse_param1}
    586 %parse-param {long parse_param2}]],
    587 	[], [[return EOF;]])
    588 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
    589 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
    590 AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1, *long parse_param2) {]])
    591 AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
    592 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param1 = parse_param1;]], [2])
    593 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param2 = parse_param2;]], [2])
    594 
    595 AT_CHECK_JAVA_MINIMAL_W_LEXER([[%lex-param {char lex_param1}]],
    596 	[], [[return EOF;]], [[YYLexer (char lex_param1) {}]])
    597 AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1) {]])
    598 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1);]])
    599 
    600 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
    601 %lex-param {char lex_param1}
    602 %lex-param {short lex_param2}]],
    603 	[], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
    604 AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2) {]])
    605 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
    606 
    607 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
    608 %parse-param {int parse_param1}
    609 %parse-param {long parse_param2}
    610 %lex-param {char lex_param1}
    611 %lex-param {short lex_param2}]],
    612 	[], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
    613 AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
    614 AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
    615 AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2, *int parse_param1, *long parse_param2) {]])
    616 AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
    617 AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
    618 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param1 = parse_param1;]], [2])
    619 AT_CHECK_JAVA_GREP([[[	 ]*this.parse_param2 = parse_param2;]], [2])
    620 
    621 AT_CLEANUP
    622 
    623 
    624 # ------------------------- #
    625 # Java throw specifications #
    626 # ------------------------- #
    627 
    628 AT_SETUP([Java throws specifications])
    629 
    630 # %define throws	- 0 1 2
    631 # %define lex-throws	- 0 1 2
    632 # %code lexer		  0 1
    633 
    634 m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws,
    635 	-1, [],
    636 	 0, [[%define lex_throws ""]],
    637 	 1, [[%define lex_throws "InterruptedException"]],
    638 	 2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
    639 
    640 m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws,
    641 	-1, [[ throws java.io.IOException]],
    642 	 0, [],
    643 	 1, [[ throws InterruptedException]],
    644 	 2, [[ throws InterruptedException, IllegalAccessException]])])
    645 
    646 m4_define([AT_JT_yylex_action], [m4_case(AT_JT_lex_throws,
    647 	-1, [[throw new java.io.IOException();]],
    648 	 0, [[return EOF;]],
    649 	 1, [[throw new InterruptedException();]],
    650 	 2, [[throw new IllegalAccessException();]])])
    651 
    652 
    653 m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws,
    654 	-1, [],
    655 	 0, [[%define throws ""]],
    656 	 1, [[%define throws "ClassNotFoundException"]],
    657 	 2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
    658 
    659 m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws,
    660 	-1, [],
    661 	 0, [],
    662 	 1, [[ throws ClassNotFoundException]],
    663 	 2, [[ throws ClassNotFoundException, InstantiationException]])])
    664 
    665 m4_define([AT_JT_parse_throws_2], [m4_case(AT_JT_throws,
    666 	-1, [],
    667 	 0, [],
    668 	 1, [[, ClassNotFoundException]],
    669 	 2, [[, ClassNotFoundException, InstantiationException]])])
    670 
    671 m4_define([AT_JT_parse_throws],
    672 	[m4_if(m4_quote(AT_JT_yylex_throws), [],
    673 		[AT_JT_yyaction_throws],
    674 		[AT_JT_yylex_throws[]AT_JT_parse_throws_2])])
    675 
    676 m4_define([AT_JT_initial_action], [m4_case(AT_JT_throws,
    677 	-1, [],
    678 	 0, [],
    679 	 1, [[%initial-action {if (true) throw new ClassNotFoundException();}]],
    680 	 2, [[%initial-action {if (true) throw new InstantiationException();}]])])
    681 
    682 m4_define([AT_JT_parse_action], [m4_case(AT_JT_throws,
    683 	-1, [],
    684 	 0, [],
    685 	 1, [[throw new ClassNotFoundException();]],
    686 	 2, [[throw new ClassNotFoundException();]])])
    687 
    688 m4_for([AT_JT_lexer], 0, 1, 1,
    689   [m4_for([AT_JT_lex_throws], -1, 2, 1,
    690     [m4_for([AT_JT_throws], -1, 2, 1,
    691       [m4_if(AT_JT_lexer, 0,
    692 	[AT_CHECK_JAVA_MINIMAL([
    693 AT_JT_throws_define
    694 AT_JT_lex_throws_define
    695 AT_JT_initial_action],
    696 [AT_JT_parse_action])],
    697 	[AT_CHECK_JAVA_MINIMAL_W_LEXER([
    698 AT_JT_throws_define
    699 AT_JT_lex_throws_define
    700 AT_JT_initial_action],
    701 [AT_JT_yylex_throws],
    702 [AT_JT_yylex_action],
    703 [],
    704 [AT_JT_parse_action])])
    705 AT_CHECK_JAVA_GREP([[ *int yylex ()]AT_JT_yylex_throws *[;]])
    706 AT_CHECK_JAVA_GREP([[ *private int yyaction ([^)]*)]AT_JT_yyaction_throws[ *]])
    707 AT_CHECK_JAVA_GREP([[ *public boolean parse ()]AT_JT_parse_throws[ *]])
    708 ])])])
    709 
    710 AT_CLEANUP
    711 
    712 
    713 # --------------------------------------------- #
    714 # Java stype, position_class and location_class #
    715 # --------------------------------------------- #
    716 
    717 AT_SETUP([Java stype, position_class and location_class])
    718 
    719 AT_CHECK_JAVA_MINIMAL([[
    720 %define stype "java.awt.Color"
    721 %type<java.awt.Color> start;
    722 %define api.location.type "MyLoc"
    723 %define api.position.type "MyPos"
    724 %code { class MyPos {} }]], [[$$ = $<java.awt.Color>1;]], [[MyPos]])
    725 AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore])
    726 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
    727 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
    728 
    729 AT_CHECK_JAVA_MINIMAL_W_LEXER([[
    730 %define stype "java.awt.Color"
    731 %type<java.awt.Color> start;
    732 %define api.location.type "MyLoc"
    733 %define api.position.type "MyPos"
    734 %code { class MyPos {} }]], [], [[return EOF;]], [],
    735 [[$$ = $<java.awt.Color>1;]],
    736 [[java.awt.Color]], [[MyPos]], [[MyLoc]])
    737 AT_CHECK([[grep 'java.awt.Color' YYParser.java]], [0], [ignore])
    738 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Position']], [1], [ignore])
    739 AT_CHECK([[$EGREP -v ' */?\*' YYParser.java | grep 'Location']], [1], [ignore])
    740 
    741 AT_CLEANUP
    742 
    743 
    744 # ----------------------------------------------- #
    745 # Java syntax error handling without error token. #
    746 # ----------------------------------------------- #
    747 
    748 AT_SETUP([Java syntax error handling without error token])
    749 
    750 AT_DATA([[YYParser.y]], [[%language "Java"
    751 
    752 %lex-param { String s }
    753 
    754 %code imports {
    755   import java.io.IOException;
    756 }
    757 
    758 %code lexer {
    759   String Input;
    760   int Position;
    761 
    762   public YYLexer (String s)
    763   {
    764     Input    = s;
    765     Position = 0;
    766   }
    767 
    768   public void yyerror (String s)
    769   {
    770     System.err.println (s);
    771   }
    772 
    773   public Object getLVal ()
    774   {
    775     return null;
    776   }
    777 
    778   public int yylex () throws IOException
    779   {
    780     if (Position >= Input.length ())
    781       return EOF;
    782     else
    783       return Input.charAt (Position++);
    784   }
    785 }
    786 
    787 %code {
    788   public static void main (String args []) throws IOException
    789   {
    790     YYParser p = new YYParser (args [0]);
    791     p.parse ();
    792   }
    793 }
    794 %%
    795 input:
    796   'a' 'a'
    797 ;
    798 ]])
    799 AT_BISON_CHECK([[YYParser.y]])
    800 AT_JAVA_COMPILE([[YYParser.java]])
    801 AT_JAVA_PARSER_CHECK([[YYParser aa]], [[0]], [[]], [[]])
    802 AT_JAVA_PARSER_CHECK([[YYParser ab]], [[0]], [[]], [[syntax error
    803 ]])
    804 AT_JAVA_PARSER_CHECK([[YYParser ba]], [[0]], [[]], [[syntax error
    805 ]])
    806 
    807 AT_CLEANUP
    808