Merge pull request #602 from parrt/accurate-ctx-sensitive-check

track context-sensitive phrases in ambiguity reporting.
This commit is contained in:
Terence Parr 2014-06-03 22:04:23 -07:00
commit ac63649b2a
3 changed files with 46 additions and 31 deletions

View File

@ -1904,22 +1904,6 @@ public class ParserATNSimulator extends ATNSimulator {
@NotNull ATNConfigSet configs)
{
if ( debug || retry_debug ) {
// ParserATNPathFinder finder = new ParserATNPathFinder(parser, atn);
// int i = 1;
// for (Transition t : dfa.atnStartState.transitions) {
// System.out.println("ALT "+i+"=");
// System.out.println(startIndex+".."+stopIndex+", len(input)="+parser.getInputStream().size());
// TraceTree path = finder.trace(t.target, parser.getContext(), (TokenStream)parser.getInputStream(),
// startIndex, stopIndex);
// if ( path!=null ) {
// System.out.println("path = "+path.toStringTree());
// for (TraceTree leaf : path.leaves) {
// List<ATNState> states = path.getPathToNode(leaf);
// System.out.println("states="+states);
// }
// }
// i++;
// }
Interval interval = Interval.of(startIndex, stopIndex);
System.out.println("reportAmbiguity "+
ambigAlts+":"+configs+

View File

@ -50,6 +50,19 @@ public class ProfilingATNSimulator extends ParserATNSimulator {
protected int currentDecision;
protected DFAState currentState;
/** At the point of LL failover, we record how SLL would resolve the conflict so that
* we can determine whether or not a decision / input pair is context-sensitive.
* If LL gives a different result than SLL's predicted alternative, we have a
* context sensitivity for sure. The converse is not necessarily true, however.
* It's possible that after conflict resolution chooses minimum alternatives,
* SLL could get the same answer as LL. Regardless of whether or not the result indicates
* an ambiguity, it is not treated as a context sensitivity because LL prediction
* was not required in order to produce a correct prediction for this decision and input sequence.
* It may in fact still be a context sensitivity but we don't know by looking at the
* minimum alternatives.
*/
protected int conflictingAltResolvedBySLL;
public ProfilingATNSimulator(Parser parser) {
super(parser,
parser.getInterpreter().atn,
@ -175,22 +188,41 @@ public class ProfilingATNSimulator extends ParserATNSimulator {
return result;
}
@Override
protected void reportContextSensitivity(@NotNull DFA dfa, int prediction, @NotNull ATNConfigSet configs, int startIndex, int stopIndex) {
decisions[currentDecision].contextSensitivities.add(
new ContextSensitivityInfo(currentDecision, configs, _input, startIndex, stopIndex)
);
super.reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
}
@Override
protected void reportAttemptingFullContext(@NotNull DFA dfa, @Nullable BitSet conflictingAlts, @NotNull ATNConfigSet configs, int startIndex, int stopIndex) {
if ( conflictingAlts!=null ) {
conflictingAltResolvedBySLL = conflictingAlts.nextSetBit(0);
}
else {
conflictingAltResolvedBySLL = configs.getAlts().nextSetBit(0);
}
decisions[currentDecision].LL_Fallback++;
super.reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex);
}
@Override
protected void reportContextSensitivity(@NotNull DFA dfa, int prediction, @NotNull ATNConfigSet configs, int startIndex, int stopIndex) {
if ( prediction != conflictingAltResolvedBySLL ) {
decisions[currentDecision].contextSensitivities.add(
new ContextSensitivityInfo(currentDecision, configs, _input, startIndex, stopIndex)
);
}
super.reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex);
}
@Override
protected void reportAmbiguity(@NotNull DFA dfa, DFAState D, int startIndex, int stopIndex, boolean exact, @Nullable BitSet ambigAlts, @NotNull ATNConfigSet configs) {
int prediction = configs.getAlts().nextSetBit(0);
if ( prediction != conflictingAltResolvedBySLL ) {
// Even though this is an ambiguity we are reporting, we can
// still detect some context sensitivities. Both SLL and LL
// are showing a conflict, hence an ambiguity, but if they resolve
// to different minimum alternatives we have also identified a
// context sensitivity.
decisions[currentDecision].contextSensitivities.add(
new ContextSensitivityInfo(currentDecision, configs, _input, startIndex, stopIndex)
);
}
decisions[currentDecision].ambiguities.add(
new AmbiguityInfo(currentDecision, configs, _input, startIndex, stopIndex, configs.fullCtx)
);

View File

@ -167,16 +167,15 @@ public class TestParserProfiler extends BaseTest {
@Test public void testContextSensitivity() throws Exception {
Grammar g = new Grammar(
"parser grammar T;\n"+
"a : e ID ;\n" +
"b : e INT ID ;\n" +
"a : '.' e ID \n" +
" | ';' e INT ID ;\n" +
"e : INT | ;\n",
lg);
DecisionInfo[] info = interpAndGetDecisionInfo(lg, g, "a", "1 x");
assertEquals(1, info.length);
DecisionInfo[] info = interpAndGetDecisionInfo(lg, g, "a", "; 1 x");
assertEquals(2, info.length);
String expecting =
"[{decision=0, contextSensitivities=1, errors=0, ambiguities=0, SLL_lookahead=3, " +
"SLL_ATNTransitions=2, SLL_DFATransitions=0, LL_Fallback=1, LL_lookahead=1, LL_ATNTransitions=1}]";
assertEquals(expecting, Arrays.toString(info));
"{decision=1, contextSensitivities=1, errors=0, ambiguities=0, SLL_lookahead=3, SLL_ATNTransitions=2, SLL_DFATransitions=0, LL_Fallback=1, LL_lookahead=3, LL_ATNTransitions=2}";
assertEquals(expecting, info[1].toString());
}
@Ignore