import IParserDebug from "../IParserDebug"; import Breakpoint from "./Breakpoint"; import ParserState from "../ParserState"; import ParserDebug from "../ParserDebug"; import ElementState from "../ElementState"; import ParseDebugUtil from "../ParseDebugUtil"; import RuleState from "../RuleState"; export default class BreakExpression implements IParserDebug { points:Array; // of Breakpoint childDebugger:IParserDebug; enabled:boolean = true; debug(state:ParserState):boolean { if (state.breakpoint == ParserDebug.DONE || state.breakpoint == ParserDebug.DONE_WITH_UNMATCHED_TEXT) { return this.childDebugger ? this.childDebugger.debug(state) : false; } if (!this.points || !this.enabled) { return false; } var stack:Array; var descendantCutoff:number = -1; if (state.isElementState()) { var estate:ElementState = state as ElementState; } var matched:boolean = false; var point:Breakpoint for ( point of this.points) { // TO_OPTIMIZE - more efficient to start with last item & work up // (but arguably easier to debug lie if (point.descends) { if (!stack) { stack = ParseDebugUtil.toStateStack(state); } descendantCutoff++; var descendantMatched:boolean = false for (var i:number = descendantCutoff; i< stack.length; i++) { var item:ParserState = stack[i]; descendantMatched = this.matchPoint(point,item, false); descendantCutoff = i; if (descendantMatched) { break; } } if (!descendantMatched) { return false; } } else { matched = this.matchPoint(point, state, true); if (!matched) { return false; } } } // iterate over breakpoints return this.childDebugger ? this.childDebugger.debug(state) : true; } // debug private matchPoint(point:Breakpoint, state:ParserState, applyFilter:boolean):boolean { if (point.isAll) { return true; } else if (point.lineIndexStr) { return state.line0 == Number(point.lineIndexStr); } else if (point.lineOnly) { return (!state.isElementState() && (state as RuleState).asLineRule); } else if (!applyFilter || this.filter(point, state) ) { var ruleState:RuleState = state as RuleState; var elementState:ElementState = state as ElementState; if (point.ruleName) { if ( ruleState && (ruleState.rule.name == point.ruleName )) { return true; } } else if (point.elementName) { if ( elementState && ( elementState.element.varName == point.elementName)) { return true } } else if (point.tokenName) { if (elementState && ( elementState.element.tokenName == point.tokenName)) { return true; } } else if (point.lineOnly) { return true; // this is taken care of by the filter } } return false; } // iteration over points private filter(point:Breakpoint, state:ParserState):boolean { return (state.breakpoint & point.filter()) != 0; } show():string { var out:string = "" if (this.points) { var br:Breakpoint for (br of this.points) { out += br.show() + "\n"; } } else { out = "" } return out; } } // class