updated the comments for SLL.

This commit is contained in:
Terence Parr 2012-10-11 12:09:38 -07:00
parent 74754d04a2
commit ad438a70ac
1 changed files with 108 additions and 34 deletions

View File

@ -1291,30 +1291,100 @@ public class ParserATNSimulator extends ATNSimulator {
} }
/** /**
SLL analysis termination. SLL prediction termination.
This function is used just for SLL. SLL can decide to give up any There are two cases: the usual combined SLL+LL parsing and
point, even immediately, failing over to full LL. To be as efficient pure SLL parsing that has no fail over to full LL.
as possible, SLL only fails over when it's positive it can't get
COMBINED SLL+LL PARSING
SLL can decide to give up any point, even immediately,
failing over to full LL. To be as efficient as possible,
though, SLL only fails over when it's positive it can't get
anywhere on more lookahead without seeing a conflict. anywhere on more lookahead without seeing a conflict.
assuming one stage parsing, an SLL confg set with only conflicting Assuming combined SLL+LL parsing, an SLL confg set with only
subsets should force failover to full LL, even if the config sets conflicting subsets should failover to full LL, even if the
don't resolve to the same alternative like {1,2} and {3,4}. The only config sets don't resolve to the same alternative like {1,2}
time SLL keeps going when there exists a conflicting subset, is when and {3,4}. If there is at least one nonconflicting set of
there is a set of nonconflicting conflicts. configs, SLL can continue with the hopes that more lookahead
will resolve via one of those nonconflicting configs.
SLL stops when it sees only conflicting config subsets Here's the prediction termination rule them: SLL (for SLL+LL
LL keeps going when there is uncertainty parsing) stops when it sees only conflicting config subsets.
In contrast, full LL keeps going when there is uncertainty.
SLL can't evaluate them 1st because it needs to create the DFA cache. PREDICATES IN SLL+LL PARSING
SLL does not evaluate predicates until after it reaches a DFA
stop state because it needs to create the DFA cache that
works in all (semantic) situations. (In contrast, full LL
evaluates predicates collected during start state computation
so it can ignore predicates thereafter.) This means that SLL
termination can totally ignore semantic predicates.
Of course, implementation-wise, ATNConfigSets combine stack
contexts but not semantic predicate contexts so we might see
two configs like this:
(s, 1, x, {}), (s, 1, x', {p})
Before testing these configurations against others, we have
to merge x and x' (w/o modifying the existing configs). For
example, we test (x+x')==x'' when looking for conflicts in
the following configs.
(s, 1, x, {}), (s, 1, x', {p}), (s, 2, x'', {})
If the configuration set has predicates, which we can test
quickly, this algorithm can make a copy of the configs and
strip out all of the predicates so that a standard
ATNConfigSet will emerge everything ignoring
predicates.
CASES:
* no conflicts & > 1 alt in set => continue
* (s, 1, x), (s, 2, x), (s, 3, z)
(s', 1, y), (s', 2, y)
yields nonconflicting set {3} (and 2 conflicting)
=> continue
* (s, 1, x), (s, 2, x),
(s', 1, y), (s', 2, y)
(s'', 1, z)
yields nonconflicting set {1} (and 2 conflicting)
=> continue
* (s, 1, x), (s, 2, x),
(s', 1, y), (s', 2, y)
yields conflicting sets only
=> stop and fail over to full LL
COMBINED SLL+LL PARSING
To handle pure SLL parsing, we can simply make the assumption
that an SLL conflict is a "real" full LL conflict. That way,
this algorithm can behave exactly like the full LL case
except for the presence of semantic predicates. But, we
ignore the semantic predicates anyway. So, we make a copy
stripped of semantic predicates and then call needMoreLookaheadSLL()
instead.
Pure SLL lookahead must continue like full LL if the union of
resolved alt sets from nonconflicting and conflicting subsets
has more than one alt. That means there's more than one
viable alternative (even in the presence of conflicts) and we
have to keep going since there is no fail over to a more
powerful algorithm.
*/ */
public boolean needMoreLookaheadSLL(@NotNull ATNConfigSet configs) { public boolean needMoreLookaheadSLL(@NotNull ATNConfigSet configs) {
return false; return false;
} }
/** /**
Full LL analysis termination. Full LL prediction termination.
Can we stop looking ahead during ATN simulation or is there some Can we stop looking ahead during ATN simulation or is there some
uncertainty as to which alternative we will ultimately pick, after uncertainty as to which alternative we will ultimately pick, after
@ -1445,25 +1515,6 @@ public class ParserATNSimulator extends ATNSimulator {
return len(viable_alts)>1 return len(viable_alts)>1
*/ */
class AltAndContextMap extends FlexibleHashMap<ATNConfig,BitSet> {
/** Code is function of (s, _, ctx, _) */
@Override
public int hashCode(ATNConfig o) {
int hashCode = 7;
hashCode = 31 * hashCode + o.state.stateNumber;
hashCode = 31 * hashCode + o.context.hashCode();
return hashCode;
}
@Override
public boolean equals(ATNConfig a, ATNConfig b) {
if ( a==b ) return true;
if ( a==null || b==null ) return false;
if ( hashCode(a) != hashCode(b) ) return false;
return a.state.stateNumber==b.state.stateNumber
&& b.context.equals(b.context);
}
}
public boolean needMoreLookaheadLL(@NotNull ATNConfigSet configs) { public boolean needMoreLookaheadLL(@NotNull ATNConfigSet configs) {
// for c in configs: // for c in configs:
// map[c] U= c.alt # map hash/equals uses s and x, not alt and not pred // map[c] U= c.alt # map hash/equals uses s and x, not alt and not pred
@ -1495,6 +1546,29 @@ public class ParserATNSimulator extends ATNSimulator {
return go; return go;
} }
/** A Map that uses just the state and the stack context as the key.
* Used by needMoreLookaheadLL.
*/
class AltAndContextMap extends FlexibleHashMap<ATNConfig,BitSet> {
/** Code is function of (s, _, ctx, _) */
@Override
public int hashCode(ATNConfig o) {
int hashCode = 7;
hashCode = 31 * hashCode + o.state.stateNumber;
hashCode = 31 * hashCode + o.context.hashCode();
return hashCode;
}
@Override
public boolean equals(ATNConfig a, ATNConfig b) {
if ( a==b ) return true;
if ( a==null || b==null ) return false;
if ( hashCode(a) != hashCode(b) ) return false;
return a.state.stateNumber==b.state.stateNumber
&& b.context.equals(b.context);
}
}
/** /**
* From grammar: * From grammar: