Home | History | Annotate | Download | only in tests
      1 # Checking the output filenames.                    -*- Autotest -*-
      2 
      3 # Copyright (C) 2000-2002, 2005-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([[Output file names.]])
     19 
     20 
     21 # AT_CHECK_OUTPUT(INPUT-FILE, [DIRECTIVES], [FLAGS], EXPECTED-FILES, [SHELLIO],
     22 #                 [ADDITIONAL-TESTS], [PRE-TESTS])
     23 # -----------------------------------------------------------------------------
     24 m4_define([AT_CHECK_OUTPUT],
     25 [AT_SETUP([[Output files: $2 $3 $5]])
     26 $7
     27 for file in $1 $4; do
     28   case "$file" in
     29     */*) mkdir -p `echo "$file" | sed 's,/.*,,'`;;
     30   esac
     31 done
     32 AT_DATA([$1],
     33 [[$2
     34 %%
     35 foo: {};
     36 ]])
     37 
     38 AT_BISON_CHECK([$3 $1 $5], 0)
     39 AT_CHECK([ls $4], [], [ignore])
     40 $6
     41 AT_CLEANUP
     42 ])
     43 
     44 AT_CHECK_OUTPUT([foo.y], [], [-dv],
     45 		[foo.output foo.tab.c foo.tab.h])
     46 
     47 # Some versions of Valgrind (at least valgrind-3.6.0.SVN-Debian) report
     48 # "fgrep: write error: Bad file descriptor" when stdout is closed, so we
     49 # skip this test group during maintainer-check-valgrind.
     50 AT_CHECK_OUTPUT([foo.y], [], [-dv],
     51 		[foo.output foo.tab.c foo.tab.h],
     52 		[>&-], [],
     53 		[AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
     54 
     55 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.c],
     56 		[foo.c foo.h foo.output])
     57 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
     58 		[foo.output foo.tab.c foo.tab.h])
     59 AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
     60 		[y.output y.tab.c y.tab.h])
     61 AT_CHECK_OUTPUT([foo.y], [], [-dv -b bar],
     62 		[bar.output bar.tab.c bar.tab.h])
     63 AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c],
     64 		[foo.c foo.dot foo.h foo.output])
     65 
     66 
     67 AT_CHECK_OUTPUT([foo.y], [%defines %verbose],      [],
     68 		[foo.output foo.tab.c foo.tab.h])
     69 AT_CHECK_OUTPUT([foo.y], [%defines %verbose %yacc],[],
     70 		[y.output y.tab.c y.tab.h])
     71 
     72 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose %yacc],[],
     73 		[y.output y.tab.c y.tab.h])
     74 
     75 # Exercise %output and %file-prefix including deprecated '='
     76 AT_CHECK_OUTPUT([foo.y], [%file-prefix "bar" %defines %verbose],      [],
     77 		[bar.output bar.tab.c bar.tab.h])
     78 AT_CHECK_OUTPUT([foo.y], [%output="bar.c" %defines %verbose %yacc],[],
     79 		[bar.output bar.c bar.h])
     80 AT_CHECK_OUTPUT([foo.y],
     81 		[%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
     82 		[],
     83 		[bar.output bar.c bar.h])
     84 
     85 
     86 # Check priorities of extension control.
     87 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose], [],
     88 		[foo.output foo.tab.cc foo.tab.hh])
     89 
     90 AT_CHECK_OUTPUT([foo.yy], [%defines %verbose ], [-o foo.c],
     91 		[foo.c foo.h foo.output])
     92 
     93 AT_CHECK_OUTPUT([foo.yy], [],
     94 		[--defines=foo.hpp -o foo.c++],
     95 		[foo.c++ foo.hpp])
     96 
     97 AT_CHECK_OUTPUT([foo.yy], [%defines "foo.hpp"],
     98 		[-o foo.c++],
     99 		[foo.c++ foo.hpp])
    100 
    101 AT_CHECK_OUTPUT([foo.yy], [],
    102 		[-o foo.c++ --graph=foo.gph],
    103 		[foo.c++ foo.gph])
    104 
    105 
    106 ## ------------ ##
    107 ## C++ output.  ##
    108 ## ------------ ##
    109 
    110 m4_define([AT_CHECK_NO_SUBDIR_PART],
    111 [# Also make sure that the includes do not refer to the subdirectory.
    112 AT_CHECK([grep 'include .subdir/' $1.cc], 1, [])
    113 AT_CHECK([grep 'include .subdir/' $1.hh], 1, [])
    114 ])
    115 
    116 AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
    117 		[foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh])
    118 
    119 AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
    120 		[foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh],
    121 		[], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
    122 
    123 AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose],
    124 		[-o subdir/foo.cc],
    125 		[subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/stack.hh subdir/position.hh],
    126 		[], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
    127 
    128 AT_CHECK_OUTPUT([gram_dir/foo.yy],
    129                 [%skeleton "lalr1.cc" %defines %verbose %file-prefix "output_dir/foo"],
    130                 [],
    131 		[output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/location.hh output_dir/stack.hh output_dir/position.hh])
    132 
    133 
    134 # AT_CHECK_CONFLICTING_OUTPUT(INPUT-FILE, DIRECTIVES, FLAGS, STDERR,
    135 #                             [EXIT-STATUS])
    136 # ------------------------------------------------------------------
    137 m4_define([AT_CHECK_CONFLICTING_OUTPUT],
    138 [AT_SETUP([Conflicting output files: $2 $3])
    139 case "$1" in
    140   */*) mkdir `echo "$1" | sed 's,/.*,,'`;;
    141 esac
    142 AT_DATA([$1],
    143 [[$2
    144 %%
    145 foo: {};
    146 ]])
    147 
    148 [cp ]$1[ expout]
    149 # Because an output file name conflict is still a warning, Bison exits
    150 # with status 0, so AT_BISON_CHECK does not realize that there may be no
    151 # output file against which to check the XML.  AT_BISON_CHECK_NO_XML
    152 # avoids that problem.
    153 AT_BISON_CHECK_NO_XML([$3 $1], $5, [], [$4])
    154 AT_CHECK([[cat $1]], [[0]], [expout])
    155 AT_CLEANUP
    156 ])
    157 
    158 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
    159 [], [--graph="foo.tab.c"],
    160 [foo.y: warning: conflicting outputs to file 'foo.tab.c'
    161 ])
    162 
    163 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
    164 [%defines "foo.output"], [-v],
    165 [foo.y: warning: conflicting outputs to file 'foo.output'
    166 ])
    167 
    168 AT_CHECK_CONFLICTING_OUTPUT([foo.y],
    169 [%skeleton "lalr1.cc" %defines], [--graph="location.hh"],
    170 [foo.y: warning: conflicting outputs to file 'location.hh'
    171 ])
    172 
    173 AT_CHECK_CONFLICTING_OUTPUT([foo.y], [], [-o foo.y],
    174 [foo.y: error: refusing to overwrite the input file 'foo.y'
    175 ], 1)
    176 
    177 
    178 # AT_CHECK_OUTPUT_FILE_NAME(FILE-NAME-PREFIX, [ADDITIONAL-TESTS])
    179 # ---------------------------------------------------------------
    180 m4_define([AT_CHECK_OUTPUT_FILE_NAME],
    181 [AT_SETUP([Output file name: $1])
    182 
    183 AT_BISON_OPTION_PUSHDEFS
    184 # Skip if platform doesn't support file name.  For example, Cygwin
    185 # doesn't support file names containing ":" or "\".
    186 AT_CHECK([[touch "]AS_ESCAPE([$1[.tmp]])[" || exit 77]])
    187 
    188 AT_DATA_GRAMMAR([glr.y],
    189 [[%glr-parser
    190 %code {
    191 ]AT_YYERROR_DECLARE_EXTERN[
    192 ]AT_YYLEX_DECLARE_EXTERN[
    193 }
    194 %%
    195 start: {};
    196 ]])
    197 AT_BISON_CHECK([-o "AS_ESCAPE([$1.c])" --defines="AS_ESCAPE([$1.h])" glr.y])
    198 AT_CHECK([ls "AS_ESCAPE([$1.c])" "AS_ESCAPE([$1.h])"], [], [ignore])
    199 AT_COMPILE([glr.o], [-c "AS_ESCAPE([$1.c])"])
    200 $2
    201 
    202 AT_DATA_GRAMMAR([cxx.y],
    203 [[%skeleton "lalr1.cc"
    204 %code { int yylex (yy::parser::semantic_type*); }
    205 %%
    206 start: {};
    207 ]])
    208 AT_BISON_CHECK([-o "AS_ESCAPE([$1.c])" --defines="AS_ESCAPE([$1.h])" cxx.y])
    209 AT_CHECK([ls "AS_ESCAPE([$1.c])" "AS_ESCAPE([$1.h])"], [], [ignore])
    210 AT_COMPILE_CXX([cxx.o], [-c "AS_ESCAPE([$1.c])"])
    211 $2
    212 
    213 AT_BISON_OPTION_POPDEFS
    214 AT_CLEANUP
    215 ])
    216 
    217 # Notice that the header file name here cannot contain
    218 # '"' since FILENAME in '#include "FILENAME"' cannot.
    219 AT_CHECK_OUTPUT_FILE_NAME([[`~!@#$%^&*()-=_+{}[]|\:;<>, .']])
    220 dnl Work around a bug in m4_expand that broke AT_SETUP in autoconf 2.62,
    221 dnl by using the definition from 2.63.
    222 m4_version_prereq([2.63], [],
    223 [m4_define([m4_expand], [_$0(-=<{($1)}>=-)])
    224 m4_define([_m4_expand],
    225 [m4_changequote([-=<{(], [)}>=-])$1m4_changequote([, ])])])
    226 AT_CHECK_OUTPUT_FILE_NAME([[(]])
    227 AT_CHECK_OUTPUT_FILE_NAME([[)]])
    228 AT_CHECK_OUTPUT_FILE_NAME([[@%:@]])
    229 AT_CHECK_OUTPUT_FILE_NAME([[@@]])
    230 AT_CHECK_OUTPUT_FILE_NAME([[@{]])
    231 AT_CHECK_OUTPUT_FILE_NAME([[@}]])
    232 AT_CHECK_OUTPUT_FILE_NAME([[@<:@]])
    233 AT_CHECK_OUTPUT_FILE_NAME([[@:>@]])
    234 
    235 
    236 # AT_TEST(SETUP-NAME, GRAMMAR, DOT-BODY)
    237 # --------------------------------------
    238 # Check that the DOT graph for GRAMMAR is DOT-BODY.
    239 m4_pushdef([AT_TEST],
    240 [AT_SETUP([$1])
    241 AT_KEYWORDS([[graph]])
    242 AT_DATA([[input.y]], [$2])
    243 AT_BISON_CHECK([[-rall --graph input.y]], [0], [[]], [[ignore]])
    244 AT_CHECK([[grep -v // input.dot]], [0],
    245 [[
    246 digraph "input.y"
    247 {
    248   node [fontname = courier, shape = box, colorscheme = paired6]
    249   edge [fontname = courier]
    250   ]$3[}
    251 ]])
    252 AT_CLEANUP
    253 ])
    254 
    255 
    256 ## ------------------------ ##
    257 ## Graph with no conflicts. ##
    258 ## ------------------------ ##
    259 
    260 AT_TEST([Graph with no conflicts],
    261 [[%%
    262 exp: a '?' b;
    263 a: ;
    264 b: 'b';
    265 ]],
    266 [[
    267   0 [label="State 0\n\l  0 $accept: . exp $end\l  1 exp: . a '?' b\l  2 a: .\l"]
    268   0 -> 1 [style=dashed label="exp"]
    269   0 -> 2 [style=dashed label="a"]
    270   0 -> "0R2" [style=solid]
    271  "0R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
    272   1 [label="State 1\n\l  0 $accept: exp . $end\l"]
    273   1 -> 3 [style=solid label="$end"]
    274   2 [label="State 2\n\l  1 exp: a . '?' b\l"]
    275   2 -> 4 [style=solid label="'?'"]
    276   3 [label="State 3\n\l  0 $accept: exp $end .\l"]
    277   3 -> "3R0" [style=solid]
    278  "3R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    279   4 [label="State 4\n\l  1 exp: a '?' . b\l  3 b: . 'b'\l"]
    280   4 -> 5 [style=solid label="'b'"]
    281   4 -> 6 [style=dashed label="b"]
    282   5 [label="State 5\n\l  3 b: 'b' .\l"]
    283   5 -> "5R3" [style=solid]
    284  "5R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    285   6 [label="State 6\n\l  1 exp: a '?' b .\l"]
    286   6 -> "6R1" [style=solid]
    287  "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
    288 ]])
    289 
    290 ## ------------------------ ##
    291 ## Graph with unsolved S/R. ##
    292 ## ------------------------ ##
    293 
    294 AT_TEST([Graph with unsolved S/R],
    295 [[%%
    296 start:
    297     'a'
    298   | empty_a 'a'
    299   | 'b'
    300   | empty_b 'b'
    301   | 'c'
    302   | empty_c 'c'
    303   ;
    304 empty_a: %prec 'a';
    305 empty_b: %prec 'b';
    306 empty_c: %prec 'c';
    307 ]],
    308 [[
    309   0 [label="State 0\n\l  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6      | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  ['b']\l  9 empty_c: .  ['c']\l"]
    310   0 -> 1 [style=solid label="'a'"]
    311   0 -> 2 [style=solid label="'b'"]
    312   0 -> 3 [style=solid label="'c'"]
    313   0 -> 4 [style=dashed label="start"]
    314   0 -> 5 [style=dashed label="empty_a"]
    315   0 -> 6 [style=dashed label="empty_b"]
    316   0 -> 7 [style=dashed label="empty_c"]
    317   0 -> "0R7d" [label="['a']", style=solid]
    318  "0R7d" [label="R7", fillcolor=5, shape=diamond, style=filled]
    319   0 -> "0R8d" [label="['b']", style=solid]
    320  "0R8d" [label="R8", fillcolor=5, shape=diamond, style=filled]
    321   0 -> "0R9d" [label="['c']", style=solid]
    322  "0R9d" [label="R9", fillcolor=5, shape=diamond, style=filled]
    323   1 [label="State 1\n\l  1 start: 'a' .\l"]
    324   1 -> "1R1" [style=solid]
    325  "1R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
    326   2 [label="State 2\n\l  3 start: 'b' .\l"]
    327   2 -> "2R3" [style=solid]
    328  "2R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    329   3 [label="State 3\n\l  5 start: 'c' .\l"]
    330   3 -> "3R5" [style=solid]
    331  "3R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
    332   4 [label="State 4\n\l  0 $accept: start . $end\l"]
    333   4 -> 8 [style=solid label="$end"]
    334   5 [label="State 5\n\l  2 start: empty_a . 'a'\l"]
    335   5 -> 9 [style=solid label="'a'"]
    336   6 [label="State 6\n\l  4 start: empty_b . 'b'\l"]
    337   6 -> 10 [style=solid label="'b'"]
    338   7 [label="State 7\n\l  6 start: empty_c . 'c'\l"]
    339   7 -> 11 [style=solid label="'c'"]
    340   8 [label="State 8\n\l  0 $accept: start $end .\l"]
    341   8 -> "8R0" [style=solid]
    342  "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    343   9 [label="State 9\n\l  2 start: empty_a 'a' .\l"]
    344   9 -> "9R2" [style=solid]
    345  "9R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
    346   10 [label="State 10\n\l  4 start: empty_b 'b' .\l"]
    347   10 -> "10R4" [style=solid]
    348  "10R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
    349   11 [label="State 11\n\l  6 start: empty_c 'c' .\l"]
    350   11 -> "11R6" [style=solid]
    351  "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
    352 ]])
    353 
    354 ## ---------------------- ##
    355 ## Graph with solved S/R. ##
    356 ## ---------------------- ##
    357 
    358 AT_TEST([Graph with solved S/R],
    359 [[%left 'a'
    360 %right 'b'
    361 %right 'c'
    362 %%
    363 start:
    364     'a'
    365   | empty_a 'a'
    366   | 'b'
    367   | empty_b 'b'
    368   | 'c'
    369   | empty_c 'c'
    370   ;
    371 empty_a: %prec 'a';
    372 empty_b: %prec 'b';
    373 empty_c: %prec 'c';
    374 ]],
    375 [[
    376   0 [label="State 0\n\l  0 $accept: . start $end\l  1 start: . 'a'\l  2      | . empty_a 'a'\l  3      | . 'b'\l  4      | . empty_b 'b'\l  5      | . 'c'\l  6      | . empty_c 'c'\l  7 empty_a: .  ['a']\l  8 empty_b: .  []\l  9 empty_c: .  []\l"]
    377   0 -> 1 [style=solid label="'b'"]
    378   0 -> 2 [style=solid label="'c'"]
    379   0 -> 3 [style=dashed label="start"]
    380   0 -> 4 [style=dashed label="empty_a"]
    381   0 -> 5 [style=dashed label="empty_b"]
    382   0 -> 6 [style=dashed label="empty_c"]
    383   0 -> "0R7" [style=solid]
    384  "0R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
    385   1 [label="State 1\n\l  3 start: 'b' .\l"]
    386   1 -> "1R3" [style=solid]
    387  "1R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    388   2 [label="State 2\n\l  5 start: 'c' .\l"]
    389   2 -> "2R5" [style=solid]
    390  "2R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
    391   3 [label="State 3\n\l  0 $accept: start . $end\l"]
    392   3 -> 7 [style=solid label="$end"]
    393   4 [label="State 4\n\l  2 start: empty_a . 'a'\l"]
    394   4 -> 8 [style=solid label="'a'"]
    395   5 [label="State 5\n\l  4 start: empty_b . 'b'\l"]
    396   5 -> 9 [style=solid label="'b'"]
    397   6 [label="State 6\n\l  6 start: empty_c . 'c'\l"]
    398   6 -> 10 [style=solid label="'c'"]
    399   7 [label="State 7\n\l  0 $accept: start $end .\l"]
    400   7 -> "7R0" [style=solid]
    401  "7R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    402   8 [label="State 8\n\l  2 start: empty_a 'a' .\l"]
    403   8 -> "8R2" [style=solid]
    404  "8R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
    405   9 [label="State 9\n\l  4 start: empty_b 'b' .\l"]
    406   9 -> "9R4" [style=solid]
    407  "9R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
    408   10 [label="State 10\n\l  6 start: empty_c 'c' .\l"]
    409   10 -> "10R6" [style=solid]
    410  "10R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
    411 ]])
    412 
    413 ## ---------------- ##
    414 ## Graph with  R/R. ##
    415 ## ---------------- ##
    416 
    417 AT_TEST([Graph with R/R],
    418 [[%%
    419 exp: a | b;
    420 a: ;
    421 b: ;
    422 ]],
    423 [[
    424   0 [label="State 0\n\l  0 $accept: . exp $end\l  1 exp: . a\l  2    | . b\l  3 a: .  [$end]\l  4 b: .  [$end]\l"]
    425   0 -> 1 [style=dashed label="exp"]
    426   0 -> 2 [style=dashed label="a"]
    427   0 -> 3 [style=dashed label="b"]
    428   0 -> "0R3" [style=solid]
    429  "0R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    430   0 -> "0R4d" [label="[$end]", style=solid]
    431  "0R4d" [label="R4", fillcolor=5, shape=diamond, style=filled]
    432   1 [label="State 1\n\l  0 $accept: exp . $end\l"]
    433   1 -> 4 [style=solid label="$end"]
    434   2 [label="State 2\n\l  1 exp: a .\l"]
    435   2 -> "2R1" [style=solid]
    436  "2R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
    437   3 [label="State 3\n\l  2 exp: b .\l"]
    438   3 -> "3R2" [style=solid]
    439  "3R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
    440   4 [label="State 4\n\l  0 $accept: exp $end .\l"]
    441   4 -> "4R0" [style=solid]
    442  "4R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    443 ]])
    444 
    445 ## ---------------------------------------- ##
    446 ## Graph with reductions with multiple LAT. ##
    447 ## ---------------------------------------- ##
    448 
    449 AT_TEST([Graph with reductions with multiple LAT],
    450 [[%%
    451 exp: a ';' | a ';' | a '.' | b '?' | b '!' | c '?' | c ';';
    452 a: ;
    453 b: ;
    454 c: ;
    455 ]],
    456 [[
    457   0 [label="State 0\n\l  0 $accept: . exp $end\l  1 exp: . a ';'\l  2    | . a ';'\l  3    | . a '.'\l  4    | . b '?'\l  5    | . b '!'\l  6    | . c '?'\l  7    | . c ';'\l  8 a: .  [';', '.']\l  9 b: .  ['?', '!']\l 10 c: .  [';', '?']\l"]
    458   0 -> 1 [style=dashed label="exp"]
    459   0 -> 2 [style=dashed label="a"]
    460   0 -> 3 [style=dashed label="b"]
    461   0 -> 4 [style=dashed label="c"]
    462   0 -> "0R8" [style=solid]
    463  "0R8" [label="R8", fillcolor=3, shape=diamond, style=filled]
    464   0 -> "0R9" [label="['?', '!']", style=solid]
    465  "0R9" [label="R9", fillcolor=3, shape=diamond, style=filled]
    466   0 -> "0R10d" [label="[';', '?']", style=solid]
    467  "0R10d" [label="R10", fillcolor=5, shape=diamond, style=filled]
    468   1 [label="State 1\n\l  0 $accept: exp . $end\l"]
    469   1 -> 5 [style=solid label="$end"]
    470   2 [label="State 2\n\l  1 exp: a . ';'\l  2    | a . ';'\l  3    | a . '.'\l"]
    471   2 -> 6 [style=solid label="';'"]
    472   2 -> 7 [style=solid label="'.'"]
    473   3 [label="State 3\n\l  4 exp: b . '?'\l  5    | b . '!'\l"]
    474   3 -> 8 [style=solid label="'?'"]
    475   3 -> 9 [style=solid label="'!'"]
    476   4 [label="State 4\n\l  6 exp: c . '?'\l  7    | c . ';'\l"]
    477   4 -> 10 [style=solid label="';'"]
    478   4 -> 11 [style=solid label="'?'"]
    479   5 [label="State 5\n\l  0 $accept: exp $end .\l"]
    480   5 -> "5R0" [style=solid]
    481  "5R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    482   6 [label="State 6\n\l  1 exp: a ';' .  [$end]\l  2    | a ';' .  [$end]\l"]
    483   6 -> "6R1" [style=solid]
    484  "6R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
    485   6 -> "6R2d" [label="[$end]", style=solid]
    486  "6R2d" [label="R2", fillcolor=5, shape=diamond, style=filled]
    487   7 [label="State 7\n\l  3 exp: a '.' .\l"]
    488   7 -> "7R3" [style=solid]
    489  "7R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    490   8 [label="State 8\n\l  4 exp: b '?' .\l"]
    491   8 -> "8R4" [style=solid]
    492  "8R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
    493   9 [label="State 9\n\l  5 exp: b '!' .\l"]
    494   9 -> "9R5" [style=solid]
    495  "9R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
    496   10 [label="State 10\n\l  7 exp: c ';' .\l"]
    497   10 -> "10R7" [style=solid]
    498  "10R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
    499   11 [label="State 11\n\l  6 exp: c '?' .\l"]
    500   11 -> "11R6" [style=solid]
    501  "11R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
    502 ]])
    503 
    504 ## ------------------------------------------------------ ##
    505 ## Graph with a reduction rule both enabled and disabled. ##
    506 ## ------------------------------------------------------ ##
    507 
    508 AT_TEST([Graph with a reduction rule both enabled and disabled],
    509 [[%%
    510 exp: ifexp | opexp | imm;
    511 ifexp: "if" exp "then" exp elseexp;
    512 elseexp: "else" exp | ;
    513 opexp: exp '+' exp;
    514 imm: '0';
    515 ]],
    516 [[
    517   0 [label="State 0\n\l  0 $accept: . exp $end\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
    518   0 -> 1 [style=solid label="\"if\""]
    519   0 -> 2 [style=solid label="'0'"]
    520   0 -> 3 [style=dashed label="exp"]
    521   0 -> 4 [style=dashed label="ifexp"]
    522   0 -> 5 [style=dashed label="opexp"]
    523   0 -> 6 [style=dashed label="imm"]
    524   1 [label="State 1\n\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" . exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
    525   1 -> 1 [style=solid label="\"if\""]
    526   1 -> 2 [style=solid label="'0'"]
    527   1 -> 7 [style=dashed label="exp"]
    528   1 -> 4 [style=dashed label="ifexp"]
    529   1 -> 5 [style=dashed label="opexp"]
    530   1 -> 6 [style=dashed label="imm"]
    531   2 [label="State 2\n\l  8 imm: '0' .\l"]
    532   2 -> "2R8" [style=solid]
    533  "2R8" [label="R8", fillcolor=3, shape=diamond, style=filled]
    534   3 [label="State 3\n\l  0 $accept: exp . $end\l  7 opexp: exp . '+' exp\l"]
    535   3 -> 8 [style=solid label="$end"]
    536   3 -> 9 [style=solid label="'+'"]
    537   4 [label="State 4\n\l  1 exp: ifexp .\l"]
    538   4 -> "4R1" [style=solid]
    539  "4R1" [label="R1", fillcolor=3, shape=diamond, style=filled]
    540   5 [label="State 5\n\l  2 exp: opexp .\l"]
    541   5 -> "5R2" [style=solid]
    542  "5R2" [label="R2", fillcolor=3, shape=diamond, style=filled]
    543   6 [label="State 6\n\l  3 exp: imm .\l"]
    544   6 -> "6R3" [style=solid]
    545  "6R3" [label="R3", fillcolor=3, shape=diamond, style=filled]
    546   7 [label="State 7\n\l  4 ifexp: \"if\" exp . \"then\" exp elseexp\l  7 opexp: exp . '+' exp\l"]
    547   7 -> 10 [style=solid label="\"then\""]
    548   7 -> 9 [style=solid label="'+'"]
    549   8 [label="State 8\n\l  0 $accept: exp $end .\l"]
    550   8 -> "8R0" [style=solid]
    551  "8R0" [label="Acc", fillcolor=1, shape=diamond, style=filled]
    552   9 [label="State 9\n\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  7 opexp: . exp '+' exp\l  7      | exp '+' . exp\l  8 imm: . '0'\l"]
    553   9 -> 1 [style=solid label="\"if\""]
    554   9 -> 2 [style=solid label="'0'"]
    555   9 -> 11 [style=dashed label="exp"]
    556   9 -> 4 [style=dashed label="ifexp"]
    557   9 -> 5 [style=dashed label="opexp"]
    558   9 -> 6 [style=dashed label="imm"]
    559   10 [label="State 10\n\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  4      | \"if\" exp \"then\" . exp elseexp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
    560   10 -> 1 [style=solid label="\"if\""]
    561   10 -> 2 [style=solid label="'0'"]
    562   10 -> 12 [style=dashed label="exp"]
    563   10 -> 4 [style=dashed label="ifexp"]
    564   10 -> 5 [style=dashed label="opexp"]
    565   10 -> 6 [style=dashed label="imm"]
    566   11 [label="State 11\n\l  7 opexp: exp . '+' exp\l  7      | exp '+' exp .  [$end, \"then\", \"else\", '+']\l"]
    567   11 -> 9 [style=solid label="'+'"]
    568   11 -> "11R7d" [label="['+']", style=solid]
    569  "11R7d" [label="R7", fillcolor=5, shape=diamond, style=filled]
    570   11 -> "11R7" [style=solid]
    571  "11R7" [label="R7", fillcolor=3, shape=diamond, style=filled]
    572   12 [label="State 12\n\l  4 ifexp: \"if\" exp \"then\" exp . elseexp\l  5 elseexp: . \"else\" exp\l  6        | .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
    573   12 -> 13 [style=solid label="\"else\""]
    574   12 -> 9 [style=solid label="'+'"]
    575   12 -> 14 [style=dashed label="elseexp"]
    576   12 -> "12R6d" [label="[\"else\", '+']", style=solid]
    577  "12R6d" [label="R6", fillcolor=5, shape=diamond, style=filled]
    578   12 -> "12R6" [style=solid]
    579  "12R6" [label="R6", fillcolor=3, shape=diamond, style=filled]
    580   13 [label="State 13\n\l  1 exp: . ifexp\l  2    | . opexp\l  3    | . imm\l  4 ifexp: . \"if\" exp \"then\" exp elseexp\l  5 elseexp: \"else\" . exp\l  7 opexp: . exp '+' exp\l  8 imm: . '0'\l"]
    581   13 -> 1 [style=solid label="\"if\""]
    582   13 -> 2 [style=solid label="'0'"]
    583   13 -> 15 [style=dashed label="exp"]
    584   13 -> 4 [style=dashed label="ifexp"]
    585   13 -> 5 [style=dashed label="opexp"]
    586   13 -> 6 [style=dashed label="imm"]
    587   14 [label="State 14\n\l  4 ifexp: \"if\" exp \"then\" exp elseexp .\l"]
    588   14 -> "14R4" [style=solid]
    589  "14R4" [label="R4", fillcolor=3, shape=diamond, style=filled]
    590   15 [label="State 15\n\l  5 elseexp: \"else\" exp .  [$end, \"then\", \"else\", '+']\l  7 opexp: exp . '+' exp\l"]
    591   15 -> 9 [style=solid label="'+'"]
    592   15 -> "15R5d" [label="['+']", style=solid]
    593  "15R5d" [label="R5", fillcolor=5, shape=diamond, style=filled]
    594   15 -> "15R5" [style=solid]
    595  "15R5" [label="R5", fillcolor=3, shape=diamond, style=filled]
    596 ]])
    597 
    598 m4_popdef([AT_TEST])
    599