예제 #1
0
        //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);
                }
            }
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        /// <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("}");
            }
        }