Skip to content

Commit

Permalink
Improved LL1Analyzer construction + add HashMap key enumeration
Browse files Browse the repository at this point in the history
- Each ATN instance now uses an own instance of the LL1Analyzer. That cannot be shared.
- Removed a forgotten debug output from the ATNSerializer.
- The HashMap now supports enumerating its keys.
- The channel value for getHiddenTokensToRight/Left in BufferedTokenStream is now marked as optional (it is already handled like that).

Signed-off-by: Mike Lischke <[email protected]>
  • Loading branch information
mike-lischke committed Dec 9, 2024
1 parent 893d8b1 commit b1169dc
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 16 deletions.
5 changes: 3 additions & 2 deletions src/BufferedTokenStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export class BufferedTokenStream implements TokenStream {
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL or
* EOF. If channel is -1, find any non default channel token.
*/
public getHiddenTokensToRight(tokenIndex: number, channel: number): Token[] | undefined {
public getHiddenTokensToRight(tokenIndex: number, channel?: number): Token[] | undefined {
if (channel === undefined) {
channel = -1;
}
Expand All @@ -356,7 +356,7 @@ export class BufferedTokenStream implements TokenStream {
* the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
* If channel is -1, find any non default channel token.
*/
public getHiddenTokensToLeft(tokenIndex: number, channel: number): Token[] | undefined {
public getHiddenTokensToLeft(tokenIndex: number, channel?: number): Token[] | undefined {
if (channel === undefined) {
channel = -1;
}
Expand Down Expand Up @@ -388,6 +388,7 @@ export class BufferedTokenStream implements TokenStream {
hidden.push(t);
}
}

if (hidden.length === 0) {
return undefined;
}
Expand Down
6 changes: 4 additions & 2 deletions src/atn/ATN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,13 @@ export class ATN {

public readonly modeToStartState: Array<TokensStartState | null> = [];

static #analyzer = new LL1Analyzer();
private analyzer: LL1Analyzer;

public constructor(grammarType: number, maxTokenType: number) {
this.grammarType = grammarType;
this.maxTokenType = maxTokenType;

this.analyzer = new LL1Analyzer(this);
}

/**
Expand All @@ -85,7 +87,7 @@ export class ATN {
return atnState.nextTokenWithinRule;
}

const next = ATN.#analyzer.look(this, atnState, undefined, ctx);
const next = this.analyzer.look(atnState, undefined, ctx);
if (!ctx) {
atnState.nextTokenWithinRule = next;
}
Expand Down
6 changes: 0 additions & 6 deletions src/atn/ATNSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ export class ATNSerializer {
case 0: {
let edgeCount = 0;
this.data.push(this.atn.states.length);
let i = 0;
for (const s of this.atn.states) {
if (s === null) { // might be optimized away
this.data.push(ATNState.INVALID_TYPE);
Expand All @@ -231,10 +230,6 @@ export class ATNSerializer {
this.nonGreedyStates.push(s.stateNumber);
}

if (i === 910) {
console.log("i", i);
}

if (s instanceof RuleStartState && s.isLeftRecursiveRule) {
this.precedenceStates.push(s.stateNumber);
}
Expand Down Expand Up @@ -262,7 +257,6 @@ export class ATNSerializer {
this.sets.set(st.set, true);
}
}
++i;
}

return edgeCount;
Expand Down
8 changes: 3 additions & 5 deletions src/atn/LL1Analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class LL1Analyzer {
*/
private static readonly hitPredicate = Token.INVALID_TYPE;

private atn: ATN;
public constructor(private atn: ATN) { }

/**
* Calculates the SLL(1) expected lookahead set for each outgoing transition
Expand Down Expand Up @@ -70,7 +70,6 @@ export class LL1Analyzer {
* If `ctx` is not `null` and the end of the outermost rule is
* reached, {@link Token//EOF} is added to the result set.
*
* @param atn the ATN
* @param s the ATN state
* @param stopState the ATN state to stop at. This can be a
* {@link BlockEndState} to detect epsilon paths through a closure.
Expand All @@ -80,11 +79,10 @@ export class LL1Analyzer {
* @returns The set of tokens that can follow `s` in the ATN in the
* specified `ctx`.
*/
public look(atn: ATN, s: ATNState, stopState?: ATNState, ctx?: ParserRuleContext): IntervalSet {
this.atn = atn;
public look(s: ATNState, stopState?: ATNState, ctx?: ParserRuleContext): IntervalSet {
const r = new IntervalSet();

const lookContext = ctx ? predictionContextFromRuleContext(atn, ctx) : null;
const lookContext = ctx ? predictionContextFromRuleContext(this.atn, ctx) : null;
this.doLook(s, stopState, lookContext, r, new HashSet(), new BitSet(), true, true);

return r;
Expand Down
4 changes: 4 additions & 0 deletions src/misc/HashMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export class HashMap<K extends IComparable, V> {
return result;
}

public keys(): Iterable<K> {
return this.backingStore.toArray().map((bucket) => { return bucket.key; });
}

public values(): Iterable<V> {
return this.backingStore.toArray().map((bucket) => { return bucket.value!; });
}
Expand Down
2 changes: 1 addition & 1 deletion src/misc/OrderedHashMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class OrderedHashMap<K extends IComparable, V> extends HashMap<K, V> {
/**
* @returns an iterable of the keys in the map, in the order they were inserted.
*/
public keys(): IterableIterator<K> {
public override keys(): IterableIterator<K> {
return this.#keys[Symbol.iterator]();
}

Expand Down

0 comments on commit b1169dc

Please sign in to comment.