UNPKG

antlr-ng

Version:

Next generation ANTLR Tool

126 lines (125 loc) 4.18 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { AtomTransition, BlockEndState, CodePointTransitions, EpsilonTransition, IntervalSet, NotSetTransition, RangeTransition, SetTransition } from "antlr4ng"; import { CharSupport } from "../misc/CharSupport.js"; import { Character } from "../support/Character.js"; import { IssueCode } from "../tool/Issues.js"; class ATNOptimizer { static { __name(this, "ATNOptimizer"); } static optimize(g, atn) { ATNOptimizer.optimizeSets(g, atn); ATNOptimizer.optimizeStates(atn); } static optimizeSets(g, atn) { if (g.isParser()) { return; } const decisions = atn.decisionToState; for (const decision of decisions) { if (decision.ruleIndex >= 0) { const rule = g.getRule(decision.ruleIndex); if (Character.isLowerCase(rule.name.codePointAt(0))) { continue; } } const setTransitions = new IntervalSet(); for (let i = 0; i < decision.transitions.length; i++) { const epsTransition = decision.transitions[i]; if (!(epsTransition instanceof EpsilonTransition)) { continue; } if (epsTransition.target.transitions.length !== 1) { continue; } const transition = epsTransition.target.transitions[0]; if (!(transition.target instanceof BlockEndState)) { continue; } if (transition instanceof NotSetTransition) { continue; } if (transition instanceof AtomTransition || transition instanceof RangeTransition || transition instanceof SetTransition) { setTransitions.addOne(i); } } const setIntervals = Array.from(setTransitions); for (let i = setIntervals.length - 1; i >= 0; i--) { const interval = setIntervals[i]; if (interval.length <= 1) { continue; } const blockEndState = decision.transitions[interval.start].target.transitions[0].target; const matchSet = new IntervalSet(); for (let j = interval.start; j <= interval.stop; j++) { const matchTransition = decision.transitions[j].target.transitions[0]; if (matchTransition instanceof NotSetTransition) { throw new Error("Not yet implemented."); } const set = matchTransition.label; for (const setInterval of set) { const a = setInterval.start; const b = setInterval.stop; if (a !== -1 && b !== -1) { for (let v = a; v <= b; v++) { if (matchSet.contains(v)) { g.tool.errorManager.grammarError( IssueCode.CharactersCollisionInSet, g.fileName, null, CharSupport.getANTLRCharLiteralForChar(v), CharSupport.getIntervalSetEscapedString(matchSet) ); break; } } } } matchSet.addSet(set); } let newTransition; const intervals = Array.from(matchSet); if (intervals.length === 1) { const matchInterval = intervals[0]; newTransition = CodePointTransitions.createWithCodePointRange( blockEndState, matchInterval.start, matchInterval.stop ); } else { newTransition = new SetTransition(blockEndState, matchSet); } decision.transitions[interval.start].target.setTransition(0, newTransition); for (let j = interval.start + 1; j <= interval.stop; j++) { const removed = decision.removeTransition(interval.start + 1); atn.removeState(removed.target); } } } } static optimizeStates(atn) { const compressed = new Array(); let i = 0; for (const s of atn.states) { if (s !== null) { compressed.push(s); s.stateNumber = i; i++; } } atn.states.splice(0, atn.states.length, ...compressed); } } export { ATNOptimizer };