public Highlighter(Raw raw) { styleDataOf = new Dictionary <string, StyleData>(); textListOf = new Dictionary <string, string[]>(); keywordDataOf = new Dictionary <string, Rules.KeywordData>(); customStyleDatas = new List <StyleData>(); foreach (Raw.RawList listI in raw.lists) { textListOf[listI.name.ToLowerInvariant()] = listI.items.ToArray(); } { bool first = true; foreach (Raw.ItemData itemDataI in raw.itemDatas) { StyleData data = new StyleData(); data.ds = Ds.GetByName(itemDataI.defStyleNum); data.name = itemDataI.name; data.color = HighlighterUtil.ParseColor(itemDataI.color); data.italic = GetVariantBool(itemDataI.italic); data.bold = GetVariantBool(itemDataI.bold); data.underline = GetVariantBool(itemDataI.underline); data.strikeout = GetVariantBool(itemDataI.strikeout); if (data.color == null && data.italic == null && data.bold == null && data.underline == null && data.strikeout == null) { data.index = data.ds.index; } else { data.index = (short)(Ds.all.Count + customStyleDatas.Count); customStyleDatas.Add(data); } styleDataOf[data.name.ToLowerInvariant()] = data; if (first) { first = false; defaultStyleData = data; } } } List <Rules.Context> contextList = new List <Rules.Context>(); contextOf = new Dictionary <string, Rules.Context>(); foreach (Raw.Context contextI in raw.contexts) { string name = contextI.name; Rules.Context context = new Rules.Context(); context.name = name; contextOf[name.ToLowerInvariant()] = context; contextList.Add(context); } List <Rules.RegExpr> regExprRules = new List <Rules.RegExpr>(); foreach (Raw.Context contextI in raw.contexts) { Rules.Context context = contextOf[contextI.name.ToLowerInvariant()]; { StyleData styleData = null; string attribute = contextI.attribute; if (attribute != null) { styleDataOf.TryGetValue(attribute.ToLowerInvariant(), out styleData); } if (styleData == null) { styleData = defaultStyleData; } context.attribute = styleData; } StyleData currentAttribute = context.attribute; context.lineEndContext = GetSwitchInfo(contextI.lineEndContext); context.fallthrough = GetBool(contextI.fallthrough); context.fallthroughContext = GetSwitchInfo(contextI.fallthroughContext); List <Rules.Rule> contextRules = new List <Rules.Rule>(); foreach (Raw.Rule ruleI in contextI.rules) { Rules.Rule rule = ParseRule(ruleI, regExprRules, context.attribute); if (rule != null) { contextRules.Add(rule); } } context.childs = contextRules.ToArray(); } awakePositions = new int[regExprRules.Count]; for (int i = 0; i < regExprRules.Count; i++) { Rules.RegExpr rule = regExprRules[i]; rule.awakePositions = awakePositions; rule.awakeIndex = i; } contexts = contextList.ToArray(); styleDataOf = null; contextOf = null; textListOf = null; }
public bool Parse(LineArray lines, int maxMilliseconds) { #if HIGHLIGHTER_DEBUG if (_debugStopwatch == null) { _debugStopwatch = new System.Diagnostics.Stopwatch(); _debugStopwatch.Start(); Console.WriteLine("HIGHLIGHTER START"); } #endif DateTime startTime = DateTime.Now; int changesBeforeTimeCheck = 0; bool timeElapsed = false; bool changed = false; stack = new PredictableList <Rules.Context>(8); stack.Add(contexts[0]); Rules.Context[] state = stack.ToArray(); bool needSetStack = false; bool lastLineChanged = false; for (int i = 0; i < lines.blocksCount; i++) { LineBlock block = lines.blocks[i]; if (timeElapsed && lastLineChanged) { while (block.count == 0) { i++; if (i >= lines.blocksCount) { block = null; break; } block = lines.blocks[i]; } if (block != null) { block.valid &= ~LineBlock.ColorValid; Line line = block.array[0]; line.startState = state; line.endState = null; } stack = null; return(changed); } { bool noChangesInBlock = (block.valid & LineBlock.ColorValid) != 0 && !lastLineChanged; if (noChangesInBlock && block.count > 0) { Rules.Context[] nextState = block.array[block.count - 1].endState; if (nextState == null) { noChangesInBlock = false; } else { state = nextState; } } if (noChangesInBlock) { needSetStack = true; continue; } } block.valid |= LineBlock.ColorValid; for (int j = 0; j < block.count; j++) { Line line = block.array[j]; if (AreEquals(line.startState, state) && line.endState != null) { state = line.endState; needSetStack = true; lastLineChanged = false; continue; } if (needSetStack) { needSetStack = false; stack.Resize(state.Length); Array.Copy(state, stack.buffer, stack.count); } line.startState = state; string text = line.Text; Array.Clear(awakePositions, 0, awakePositions.Length); int position = 0; int count = line.charsCount; Rules.Rule lastMatched = null; while (position < count) { Rules.Context context = stack.count > 0 ? stack.Peek() : contexts[0]; lastMatched = null; foreach (Rules.Rule rule in context.childs) { int nextPosition; if ((rule.column == -1 || position == rule.column) && rule.Match(text, position, out nextPosition)) { if (!rule.lookAhead) { for (; position < nextPosition; position++) { line.chars[position].style = rule.attribute.index; } } if (rule.childs != null && position < count) { foreach (Rules.Rule childRule in rule.childs) { int childNextPosition; if (childRule.Match(text, nextPosition, out childNextPosition)) { for (; position < childNextPosition; position++) { line.chars[position].style = childRule.attribute.index; } Switch(rule.context); } } } Switch(rule.context); lastMatched = rule; break; } } if (lastMatched == null) { if (context.fallthrough) { Switch(context.fallthroughContext); } else { line.chars[position].style = context.attribute.index; position++; } } } if (lastMatched == null || !lastMatched.isLineContinue) { while (stack.count > 0) { Rules.Context contextI = stack.Peek(); if (contextI.lineEndContext.next == null && contextI.lineEndContext.pops == 0) { break; } Switch(contextI.lineEndContext); } } if (AreEquals(stack, state)) { line.endState = state; } else { state = stack.ToArray(); line.endState = state; } changesBeforeTimeCheck++; lastLineChanged = true; changed = true; } if (changesBeforeTimeCheck > 50) { changesBeforeTimeCheck = 0; DateTime nextTime = DateTime.Now; timeElapsed = (nextTime - startTime).TotalMilliseconds > maxMilliseconds; if (timeElapsed) { startTime = nextTime; } } } stack = null; lastParsingChanged = changed; if (!changed && lines.ranges != null) { foreach (StyleRange range in lines.ranges) { lines.SetStyleRange(range); } } #if HIGHLIGHTER_DEBUG if (!changed) { _debugStopwatch.Stop(); Console.WriteLine("HIGHLIGHTER TIME: " + (_debugStopwatch.Elapsed.TotalMilliseconds / 1000).ToString("0.00")); } #endif return(changed); }
private Rules.Rule ParseRule(Raw.Rule rawRule, List <Rules.RegExpr> regExprRules, StyleData parentStyleData) { Rules.Rule commonRule = null; if (rawRule.type == "keyword") { string[] list; string key = rawRule.String.ToLowerInvariant(); textListOf.TryGetValue(key, out list); if (list != null) { bool casesensitive = GetBool(rawRule.general.keywordsCasesensitive, true); Rules.KeywordData cachedData; keywordDataOf.TryGetValue(key, out cachedData); Rules.KeywordData data = null; for (Rules.KeywordData dataI = cachedData; dataI != null; dataI = dataI.next) { if (dataI.casesensitive == casesensitive) { data = dataI; break; } } if (data == null) { data = new Rules.KeywordData(list, casesensitive, cachedData); keywordDataOf[key] = data; } commonRule = new Rules.Keyword( data, rawRule.general.keywordsWeakDeliminator ?? "", rawRule.general.keywordsAdditionalDeliminator ?? ""); } } else if (rawRule.type == "DetectChar") { Rules.DetectChar rule = new Rules.DetectChar(); rule.char0 = CharOf(rawRule.char0); commonRule = rule; } else if (rawRule.type == "Detect2Chars") { Rules.Detect2Chars rule = new Rules.Detect2Chars(); rule.char0 = CharOf(rawRule.char0); rule.char1 = CharOf(rawRule.char1); commonRule = rule; } else if (rawRule.type == "AnyChar") { Rules.AnyChar rule = new Rules.AnyChar(); rule.chars = rawRule.String; commonRule = rule; } else if (rawRule.type == "StringDetect") { Rules.StringDetect rule = new Rules.StringDetect(); rule.insensitive = GetBool(rawRule.insensitive); rule.text = rawRule.String; commonRule = rule; } else if (rawRule.type == "WordDetect") { commonRule = new Rules.WordDetect(rawRule.String, GetBool(rawRule.insensitive)); } else if (rawRule.type == "RegExpr") { Rules.RegExpr rule = new Rules.RegExpr(); string regex = rawRule.String; rule.regex = new Regex( HighlighterUtil.FixRegexUnicodeChars(GetBool(rawRule.minimal) ? HighlighterUtil.LazyOfRegex(regex) : regex), (GetBool(rawRule.insensitive) ? RegexOptions.IgnoreCase : RegexOptions.None) ); commonRule = rule; regExprRules.Add(rule); } else if (rawRule.type == "Int") { commonRule = new Rules.Int(); } else if (rawRule.type == "Float") { commonRule = new Rules.Float(); } else if (rawRule.type == "HlCOct") { commonRule = new Rules.HlCOct(); } else if (rawRule.type == "HlCHex") { commonRule = new Rules.HlCHex(); } else if (rawRule.type == "RangeDetect") { Rules.RangeDetect rule = new Rules.RangeDetect(); rule.char0 = CharOf(rawRule.char0); rule.char1 = CharOf(rawRule.char1); commonRule = rule; } else if (rawRule.type == "DetectSpaces") { commonRule = new Rules.DetectSpaces(); } else if (rawRule.type == "DetectIdentifier") { commonRule = new Rules.DetectIdentifier(); } else if (rawRule.type == "HlCStringChar") { commonRule = new Rules.HlCStringChar(); } else if (rawRule.type == "HlCChar") { commonRule = new Rules.HlCChar(); } else if (rawRule.type == "LineContinue") { commonRule = new Rules.LineContinue(); } if (commonRule != null) { { StyleData styleData = null; string attribute = rawRule.attribute; if (attribute != null) { styleDataOf.TryGetValue(attribute.ToLowerInvariant(), out styleData); } if (styleData == null) { styleData = parentStyleData ?? defaultStyleData; } commonRule.attribute = styleData; } commonRule.lookAhead = GetBool(rawRule.lookAhead); int column = GetInt(rawRule.column, -1); if (GetBool(rawRule.firstNonSpace)) { commonRule.column = 0; } else { commonRule.column = column; } commonRule.context = GetSwitchInfo(!string.IsNullOrEmpty(rawRule.context) ? rawRule.context : "#stay"); List <Rules.Rule> childs = null; foreach (Raw.Rule childI in rawRule.childs) { Rules.Rule child = ParseRule(childI, regExprRules, commonRule.attribute); if (child != null) { if (childs == null) { childs = new List <Rules.Rule>(); } childs.Add(child); } } if (childs != null) { commonRule.childs = childs.ToArray(); } } return(commonRule); }