Merge pull request #602 from parrt/accurate-ctx-sensitive-check
track context-sensitive phrases in ambiguity reporting.
This commit is contained in:
commit
ac63649b2a
|
@ -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+
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue