Implement %define lr.default_rules.

Its value describes the states that are permitted to contain
default rules: "all", "consistent", or "accepting".
* src/reader.c (reader): Default lr.default_rules to "all".
Check for a valid lr.default_rules value.
* src/lalr.c (state_lookahead_tokens_count): If lr.default_rules
is "accepting", then only mark the accepting state as
consistent.
(initialize_LA): Tell state_lookahead_tokens_count whether
lr.default_rules is "accepting".
* src/tables.c (action_row): If lr.default_rules is not "all",
then disable default rules in inconsistent states.
* src/print.c (print_reductions): Use this opportunity to
perform some assertions about whether lr.default_rules was
obeyed correctly.
* tests/local.at (AT_TEST_TABLES_AND_PARSE): New macro that
helps with checking the parser tables for a grammar.
* tests/input.at (%define lr.default_rules invalid values): New
test group.
* tests/reduce.at (AT_TEST_LR_DEFAULT_RULES): New macro using
AT_TEST_TABLES_AND_PARSE.
(`no %define lr.default_rules'): New test group generated by
AT_TEST_LR_DEFAULT_RULES.
(`%define lr.default_rules "all"'): Likewise.
(`%define lr.default_rules "consistent"'): Likewise.
(`%define lr.default_rules "accepting"'): Likewise.
This commit is contained in:
Joel E. Denny
2009-04-20 00:55:50 -04:00
parent 72e727f2ec
commit 7254f6a840
8 changed files with 428 additions and 22 deletions

View File

@@ -1,5 +1,6 @@
# Exercising Bison Grammar Reduction. -*- Autotest -*-
# Copyright (C) 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
# Copyright (C) 2001, 2002, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -355,3 +356,147 @@ input.y:3.1-3: fatal error: start symbol exp does not derive any sentence
]])
AT_CLEANUP
## -------------------------- ##
## %define lr.default_rules. ##
## -------------------------- ##
# AT_TEST_LR_DEFAULT_RULES(GRAMMAR, INPUT, TABLES)
# ------------------------------------------------
m4_define([AT_TEST_LR_DEFAULT_RULES],
[
AT_TEST_TABLES_AND_PARSE([[no %define lr.default_rules]],
[[all]], [[]],
[[]],
[$1], [$2], [[]], [$3])
AT_TEST_TABLES_AND_PARSE([[%define lr.default_rules "all"]],
[[all]], [[]],
[[%define lr.default_rules "all"]],
[$1], [$2], [[]], [$3])
AT_TEST_TABLES_AND_PARSE([[%define lr.default_rules "consistent"]],
[[consistent]], [[]],
[[%define lr.default_rules "consistent"]],
[$1], [$2], [[]], [$3])
AT_TEST_TABLES_AND_PARSE([[%define lr.default_rules "accepting"]],
[[accepting]], [[]],
[[%define lr.default_rules "accepting"]],
[$1], [$2], [[]], [$3])
])
AT_TEST_LR_DEFAULT_RULES([[
/* The start state is consistent and has a shift on 'a' and no reductions.
After pushing the b below, enter an inconsistent state that has a shift and
one reduction with one lookahead. */
start:
a b
| a b 'a'
| a c 'b'
;
/* After shifting this 'a', enter a consistent state that has no shift and 1
reduction with multiple lookaheads. */
a: 'a' ;
/* After the previous reduction, enter an inconsistent state that has no shift
and multiple reductions. The first reduction has more lookaheads than the
second, so the first should always be preferred as the default rule if
enabled. The second reduction has one lookahead. */
b: ;
c: ;
]],
dnl Visit each state mentioned above.
[['a', 'a']],
[[state 0
0 $accept: . start $end
1 start: . a b
2 | . a b 'a'
3 | . a c 'b'
4 a: . 'a'
'a' shift, and go to state 1
start go to state 2
a go to state 3
state 1
4 a: 'a' .]AT_COND_CASE([[accepting]], [[ [$end, 'a', 'b']
$end reduce using rule 4 (a)
'a' reduce using rule 4 (a)
'b' reduce using rule 4 (a)]], [[
$default reduce using rule 4 (a)]])[
state 2
0 $accept: start . $end
$end shift, and go to state 4
state 3
1 start: a . b
2 | a . b 'a'
3 | a . c 'b'
5 b: . [$end, 'a']
6 c: . ['b']]AT_COND_CASE([[all]], [[
'b' reduce using rule 6 (c)
$default reduce using rule 5 (b)]], [[
$end reduce using rule 5 (b)
'a' reduce using rule 5 (b)
'b' reduce using rule 6 (c)]])[
b go to state 5
c go to state 6
state 4
0 $accept: start $end .
$default accept
state 5
1 start: a b . [$end]
2 | a b . 'a'
'a' shift, and go to state 7
]AT_COND_CASE([[all]], [[$default]], [[$end]])[ reduce using rule 1 (start)
state 6
3 start: a c . 'b'
'b' shift, and go to state 8
state 7
2 start: a b 'a' .]AT_COND_CASE([[accepting]], [[ [$end]
$end reduce using rule 2 (start)]], [[
$default reduce using rule 2 (start)]])[
state 8
3 start: a c 'b' .]AT_COND_CASE([[accepting]], [[ [$end]
$end reduce using rule 3 (start)]], [[
$default reduce using rule 3 (start)]])[
]])