//Adds a single context member to the compiling string. private void AddMember(ContextMember member, string ctxName, ref StringBuilder text, IroPrecompileData data) { if (member.Type == ContextMemberType.Pattern) { //Normal pattern. var pattern = ((PatternContextMember)member); var patternStyles = GetPatternStyles(pattern.Styles, data); text.AppendLine("{"); text.AppendLine("\"token\": \"" + patternStyles[0].AceScope + "\","); //Replace normal '\' with '\\', since it's inside another string. text.AppendLine("\"regex\": \"" + pattern.Data.Replace("\\", "\\\\") + "\""); //Close pattern. text.AppendLine("},"); } else if (member.Type == ContextMemberType.InlinePush) { //Inline push pattern. var ilp = ((InlinePushContextMember)member); var ilpStyles = GetPatternStyles(ilp.Styles, data); //Get the push data. text.AppendLine("{"); text.AppendLine("\"token\": \"" + ilpStyles[0].AceScope + "\","); //Replace normal '\' with '\\', since it's inside another string. text.AppendLine("\"regex\": \"" + ilp.Data.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\","); //Queue an ILP context to be created later (if it's not already created). string pushCtxName; var ilpPushTuple = new Tuple <string, string>(ctxName, ilp.Data); if (!contextsCreated.ContainsKey(ilpPushTuple)) { pushCtxName = "helper_" + ShortId.Generate(7); //Queue and add to the "done" list. QueueILPContext(pushCtxName, ilp); contextsCreated.Add(ilpPushTuple, pushCtxName); } else { //Already created one for this regex. pushCtxName = contextsCreated[ilpPushTuple]; } text.AppendLine("\"push\": \"" + pushCtxName + "\""); //Close pattern. text.AppendLine("},"); } else if (member.Type == ContextMemberType.Include) { //Include. //Find the top-level context being included. var toInclude = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (toInclude == null) { Error.Compile("No context with name '" + member.Data + "' exists to include."); return; } //Make sure toInclude isn't this one. if (toInclude.Name == ctxName) { Error.CompileWarning("Recursive include loop detected, ignoring it."); return; } //Loop over all members in toInclude, include them. foreach (var memberInc in toInclude.Members) { AddMember(memberInc, toInclude.Name, ref text, data); } } }
private void AddContextMember(ContextMember member, string ctxName, IroPrecompileData data, ref RubyStringMaker text) { //What type is it? switch (member.Type) { case ContextMemberType.Pattern: //Normal pattern. var pattern = (PatternContextMember)member; string rule = "rule /"; rule += pattern.Data + "/"; //Get styles for pattern. Do they match up? var styles = GetPatternStyles(pattern.Styles, data); if (styles.Count > 1) { //Grouped. rule += " do"; text.AppendLine(rule); text.TabIn(); rule = "groups "; foreach (var style in styles) { rule += style.PygmentsScope.Replace(".", "::") + ", "; } rule = rule.TrimEnd(' ', ','); text.AppendLine(rule); text.TabOut(); text.AppendLine("end"); } else if (styles.Count != 0) { //Ungrouped. rule += ", " + styles[0].PygmentsScope.Replace(".", "::"); text.AppendLine(rule); } else { Error.Compile("No styles given for rule '" + pattern.Data + "'."); return; } break; case ContextMemberType.InlinePush: //Inline push pattern. var ilp = (InlinePushContextMember)member; string ruleIlp = "rule /" + ilp.Data + "/"; //Get styles for pattern. Do they match up? var pushStyles = GetPatternStyles(ilp.Styles, data); string helperName = "helper_" + ShortId.Generate(7); //Is the helper already made? var madeHelper = queuedContexts.FirstOrDefault(x => x.Key.Item1 == ctxName && x.Value.Data == ilp.Data); if (madeHelper.Key != null) { //Already made a helper, set the name. helperName = madeHelper.Key.Item2; } if (pushStyles.Count > 1) { //Grouped. ruleIlp += " do"; text.AppendLine(ruleIlp); text.TabIn(); ruleIlp = "groups "; foreach (var style in pushStyles) { ruleIlp += style.PygmentsScope.Replace(".", "::") + ", "; } ruleIlp = ruleIlp.TrimEnd(' ', ','); text.AppendLine(ruleIlp); //Add the push. ruleIlp = "push :" + helperName; //Tab out, end. text.TabOut(); text.AppendLine("end"); } else if (pushStyles.Count != 0) { //Ungrouped. ruleIlp += ", " + pushStyles[0].PygmentsScope.Replace(".", "::") + ", :" + helperName; text.AppendLine(ruleIlp); } else { Error.Compile("No styles given for rule '" + ilp.Data + "'."); return; } //Queue the push scope if not already pushed. if (madeHelper.Key == null) { QueueILPScope(ctxName, helperName, ilp); } break; case ContextMemberType.Include: //Get the context to include. var ctx = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (ctx == null) { Error.Compile("Context mentioned to include '" + member.Data + "' does not exist."); return; } //Skip? if (includedThisRun.Contains(member.Data)) { return; } //Include all members recursively with update list. includedThisRun.Add(member.Data); foreach (var mem in ctx.Members) { AddContextMember(mem, ctxName, data, ref text); } break; } }
private void AddContextMember(string ctxName, ContextMember member, IroPrecompileData data, ref PyStringMaker text) { //What's the context member type? string regTxt = ""; switch (member.Type) { //Normal pattern. case ContextMemberType.Pattern: var pat = (PatternContextMember)member; regTxt += "(u'" + pat.Data.Replace("\\", "\\\\") + "', bygroups("; //Get styles out. var styles = GetPatternStyles(pat.Styles, data); //Apply styles. foreach (var style in styles) { regTxt += style.PygmentsScope + ", "; } regTxt = regTxt.TrimEnd(',', ' '); //Close bygroups, end pattern. regTxt += ")),"; text.AppendLine(regTxt); return; //Inline push. case ContextMemberType.InlinePush: var ilp = (InlinePushContextMember)member; regTxt += "(u'" + ilp.Data.Replace("\\", "\\\\") + "', bygroups("; //Get push styles out. var pushStyles = GetPatternStyles(ilp.Styles, data); //Add and close bygroups scope. foreach (var style in pushStyles) { regTxt += style.PygmentsScope + ", "; } regTxt = regTxt.TrimEnd(',', ' '); regTxt += ")"; //Add the push scope with a random name. string helperName = "helper_" + ShortId.Generate(7); QueueContext(ctxName, helperName, ilp); regTxt += ", '" + helperName + "'),"; text.AppendLine(regTxt); return; //Include. case ContextMemberType.Include: //Get the context to include. var ctx = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (ctx == null) { Error.Compile("Context mentioned to include '" + member.Data + "' does not exist."); return; } //Skip? if (includedThisRun.Contains(member.Data)) { return; } //Include all members recursively with update list. includedThisRun.Add(member.Data); foreach (var mem in ctx.Members) { AddContextMember(ctxName, mem, data, ref text); } return; } }
/// <summary> /// Adds a single context member to the text. /// </summary> private void AddMember(ContextMember member, IroPrecompileData data, ref StringBuilder text) { if (member.Type == ContextMemberType.Pattern) { //Normal pattern. Get styles out. var pattern = ((PatternContextMember)member); var styles = GetPatternStyles(pattern.Styles, data); //Check if the groups match. if (!Compiler.GroupsMatch(pattern.Data, styles.Count)) { Error.Compile("Amount of capture groups does not line up with the amount of assigned styles."); return; } //Add to text. text.AppendLine("{"); //Make sure to replace backslashes and quotes. text.AppendLine("'match': '" + pattern.Data.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); if (styles.Count > 1) { //Multiple styles. text.AppendLine("'captures': {"); for (int i = 0; i < styles.Count; i++) { //Numbered styles. text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + styles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); } else { //Single style. text.AppendLine("'name': '" + styles[0].TextmateScope + "." + data.Name + "'"); } text.AppendLine("}"); } else if (member.Type == ContextMemberType.InlinePush) { //Inline push pattern. var ilp = ((InlinePushContextMember)member); var styles = GetPatternStyles(ilp.Styles, data); //Add starting styles. text.AppendLine("{"); text.AppendLine("'begin': '" + ilp.Data.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); text.AppendLine("'beginCaptures': {"); for (int i = 0; i < styles.Count; i++) { text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + styles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); //Is a default style assigned? int defaultStyleIndex = ilp.Patterns.FindIndex(x => x.Type == ContextMemberType.DefaultStyle); if (defaultStyleIndex != -1) { //Are other patterns defined? if (ilp.Patterns.FindIndex(x => x.Type == ContextMemberType.Pattern) != -1) { //Warn the user. Error.CompileWarning("You cannot define unique patterns when a 'default_style' attribute is applied. Ignoring them."); } //Get the style out. var style = GetPatternStyles(new List <string>() { ilp.Patterns[defaultStyleIndex].Data }, data); //Add default content name. text.AppendLine("'contentName': '" + style[0].TextmateScope + "." + data.Name + "'"); } else { //Actual patterns defined, not just default. //Begin patterns, capture all "pattern" sets and includes and queue them. text.AppendLine("'patterns': ["); //Include the queued context. if (ilp.Patterns.Count != 0) { string helperName = "helper_" + ShortId.Generate(7); text.AppendLine("{"); text.AppendLine("'include': '#" + helperName + "'"); text.AppendLine("}"); //Queue it. QueueContext(helperName, ilp.Patterns); } text.AppendLine("]"); } //Patterns done, pop condition & styles. var popStyles = GetPatternStyles(ilp.PopStyles, data); //Patterns match up with context groups? if (!Compiler.GroupsMatch(ilp.PopData, popStyles.Count)) { Error.Compile("Mismatch between capture groups and number of styles for pop with regex '" + ilp.PopData + "'."); return; } //Okay, add pop data. text.AppendLine("'end': '" + ilp.PopData.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); text.AppendLine("'endCaptures': {"); for (int i = 0; i < popStyles.Count; i++) { text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + popStyles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); //Close whole ILP. text.AppendLine("}"); } else if (member.Type == ContextMemberType.Include) { //Append an include. text.AppendLine("{"); text.AppendLine("'include': '#" + member.Data + "'"); text.AppendLine("}"); } }