예제 #1
0
        /// <summary>
        /// Gets a list of styles for a specific pattern context member.
        /// </summary>
        private List <IroStyle> GetPatternStyles(List <string> styleNames, IroPrecompileData data)
        {
            //Check that styles exist, and try to get the first one out.
            if (styleNames.Count == 0)
            {
                Error.Compile("No style was defined for a pattern. All styles must have patterns.");
                return(null);
            }

            //Get all the patterns out.
            var styles = new List <IroStyle>();

            foreach (var style in styleNames)
            {
                //Get the styles form the style list.
                int index = data.Styles.FindIndex(x => x.Name == style);
                if (index == -1)
                {
                    Error.Compile("A style '" + style + "' is referenced in a pattern, but it is not defined in the style map.");
                    return(null);
                }

                styles.Add(data.Styles[index]);
            }

            //Make sure all the patterns have textmate scopes.
            if (styles.Where(x => x.PygmentsScope != null).Count() != styles.Count)
            {
                Error.Compile("One or more styles for a pattern does not have a Pygments scope defined.");
                return(null);
            }

            return(styles);
        }
예제 #2
0
        /// <summary>
        /// Adds a context that has been queued to the builder.
        /// </summary>
        private void AddQueuedContext(string ctxName, InlinePushContextMember ilp, IroPrecompileData data, ref StringBuilder text)
        {
            //Begin this context.
            text.AppendLine("\"" + ctxName + "\": [");

            //Get styles out for pop rule.
            var popStyles = GetPatternStyles(ilp.PopStyles, data);

            //Add the pop rule.
            text.AppendLine("{");
            text.AppendLine("\"token\": \"" + popStyles[0].AceScope + "\",");
            text.AppendLine("\"regex\": \"" + ilp.PopData.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\",");
            text.AppendLine("\"next\": \"pop\"");
            text.AppendLine("},");

            //Add all patterns for the ILP.
            foreach (var pattern in ilp.Patterns)
            {
                AddMember(pattern, ctxName, ref text, data);
            }

            //Add the default style.
            text.AppendLine("{");
            text.AppendLine("defaultToken: \"text\"");
            text.AppendLine("}");

            //End this context.
            text.AppendLine("],");
        }
예제 #3
0
        /// <summary>
        /// Turns Iro precompile data into a compiled Rouge target.
        /// </summary>
        public CompileResult Compile(IroPrecompileData data)
        {
            var text = new RubyStringMaker();

            //Add the coding header and modules.
            text.AppendLine("# -*- coding: utf-8 -*- #");
            text.AppendLine();
            text.AppendLine("module Rouge");
            text.TabIn();
            text.AppendLine("module Lexers");
            text.TabIn();
            text.AppendLine("class " + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + " < RegexLexer");
            text.TabIn();

            //Add basic metadata.
            text.AppendLine("title \"" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "\"");
            text.AppendLine("tag '" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'");
            text.AppendLine("mimetypes 'text/x-" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'");
            string fileTypes = "";

            foreach (var ext in data.FileExtensions)
            {
                fileTypes += "'*." + ext + "', ";
            }
            fileTypes = fileTypes.TrimEnd(',', ' ');
            text.AppendLine("filenames " + fileTypes);
            text.AppendLine();

            //Check the main context exists.
            var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main");

            if (mainCtx == null)
            {
                Error.Compile("No context exists named 'main' to use as the root context. Add a 'main' context.");
                return(null);
            }
            AddContext(mainCtx, "root", data, ref text);

            //Add all the queued helpers.
            while (queuedContexts.Count != 0)
            {
                var item = queuedContexts.ElementAt(0);
                AddILPContext(item.Key.Item1, item.Key.Item2, item.Value, data, ref text);
                queuedContexts.Remove(item.Key);
            }

            //Close all the modules.
            text.TabOut();
            text.AppendLine("end");
            text.TabOut();
            text.AppendLine("end");
            text.TabOut();
            text.AppendLine("end");

            return(new CompileResult()
            {
                GeneratedFile = text.ToString(),
                Target = Target.Rouge
            });
        }
예제 #4
0
        /// <summary>
        /// Processes the currently queued contexts.
        /// </summary>
        private void ProcessQueuedContexts(IroPrecompileData data, ref StringBuilder text)
        {
            foreach (var context in queuedContexts)
            {
                AddContext(new IroContext(context.Key)
                {
                    Members = context.Value
                }, data, ref text);
            }

            queuedContexts = new Dictionary <string, List <ContextMember> >();
        }
예제 #5
0
        /// <summary>
        /// Adds a single context to the text grammar.
        /// </summary>
        private void AddContext(IroContext context, IroPrecompileData data, ref StringBuilder text)
        {
            //Name of context, start of patterns.
            text.AppendLine("'" + context.Name + "': {");
            text.AppendLine("'patterns': [");

            //Loop over, add members.
            foreach (var member in context.Members)
            {
                AddMember(member, data, ref text);
            }

            text.AppendLine("]");
            text.AppendLine("}");
        }
예제 #6
0
        //Adds a single context to the grammar string.
        private void AddContext(IroContext ctx, IroPrecompileData data, ref PyStringMaker text)
        {
            //Open the context.
            text.AppendLine("'" + ctx.Name + "' : [");
            text.TabIn();

            //Add context members.
            foreach (var member in ctx.Members)
            {
                AddContextMember(ctx.Name, member, data, ref text);
            }
            text.TrimEnd(',', ' ');

            text.TabOut();
            text.AppendLine("],");
        }
예제 #7
0
        //Adds a single context to the text.
        private void AddContext(IroContext ctx, string name, IroPrecompileData data, ref RubyStringMaker text)
        {
            //Reset includes, create new state.
            includedThisRun = new List <string>();
            text.AppendLine("state:" + name);
            text.TabIn();

            //Loop over rules, add them.
            foreach (var member in ctx.Members)
            {
                AddContextMember(member, ctx.Name, data, ref text);
            }

            text.TabOut();
            text.AppendLine("end");
        }
예제 #8
0
        /// <summary>
        /// Gets a list of styles for a specific pattern context member.
        /// </summary>
        private List <IroStyle> GetPatternStyles(List <string> styleNames, IroPrecompileData data)
        {
            //Check that styles exist, and try to get the first one out.
            if (styleNames.Count == 0)
            {
                Error.Compile("No style was defined for a pattern. All styles must have patterns.");
                return(null);
            }

            //Get all the patterns out.
            var styles = new List <IroStyle>();

            foreach (var style in styleNames)
            {
                //Get the styles form the style list.
                int index = data.Styles.FindIndex(x => x.Name == style);
                if (index == -1)
                {
                    Error.Compile("A style '" + style + "' is referenced in a pattern, but it is not defined in the style map.");
                    return(null);
                }

                styles.Add(data.Styles[index]);
            }

            //Make sure all the patterns have textmate scopes.
            foreach (var style in styles)
            {
                if (style.AceScope == null)
                {
                    //Missing ace, can inherit?
                    if (style.TextmateScope == null)
                    {
                        Error.Compile("No Textmate or Atom scope is defined for style '" + style.Name + "'.");
                        return(null);
                    }

                    style.AceScope = style.TextmateScope;
                }
            }

            return(styles);
        }
예제 #9
0
        //Adds a single context to the compiling string.
        private void AddContext(IroContext thisCtx, string ctxName, IroPrecompileData data, ref StringBuilder text)
        {
            //Begin this context.
            text.AppendLine("\"" + ctxName + "\": [");

            //Loop over the context, add all members.
            for (int i = 0; i < thisCtx.Members.Count; i++)
            {
                var member = thisCtx.Members[i];
                AddMember(member, ctxName, ref text, data);
            }

            //Add the default member.
            text.AppendLine("{");
            text.AppendLine("defaultToken: \"text\"");
            text.AppendLine("}");

            //Close the context.
            text.AppendLine("],");
        }
예제 #10
0
        /// <summary>
        /// Compiles precompile data into an Atom Textmate file.
        /// </summary>
        public CompileResult Compile(IroPrecompileData data)
        {
            var text = new StringBuilder();

            //Add the file extensions.
            text.AppendLine("'fileTypes': [");
            foreach (var ext in data.FileExtensions)
            {
                text.AppendLine("'" + ext + "'");
            }
            text.AppendLine("]");

            //Name of the grammar.
            text.AppendLine("'name': '" + data.Name + "'");

            //Template for including main.
            text.AppendLine("'patterns' : [");
            text.AppendLine("{");
            text.AppendLine("'include': '#main'");
            text.AppendLine("}");
            text.AppendLine("]");

            //Root scope name.
            text.AppendLine("'scopeName': '" + data.Name + "'");

            //UUID (if one exists).
            text.AppendLine("'uuid': '" + data.UUID + "'");

            //Main repo for all patterns.
            text.AppendLine("'repository': {");

            //Loop over contexts and add them. Make sure main is first.
            var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main");

            if (mainCtx == null)
            {
                Error.Compile("No main context exists to start the grammar with.");
                return(null);
            }

            //Add main.
            AddContext(mainCtx, data, ref text);
            ProcessQueuedContexts(data, ref text);

            //Loop over other contexts and add.
            foreach (var ctx in data.Contexts)
            {
                //Skip main, already processed.
                if (ctx.Name == "main")
                {
                    continue;
                }

                AddContext(ctx, data, ref text);
                ProcessQueuedContexts(data, ref text);
            }

            //Close set, return.
            text.AppendLine("}");
            return(new CompileResult()
            {
                GeneratedFile = FormatCScript(text.ToString()),
                Target = Target.Atom
            });
        }
예제 #11
0
        /// <summary>
        /// Compiles pre-compile data into a Pygments grammar file.
        /// </summary>
        public CompileResult Compile(IroPrecompileData data)
        {
            var text = new PyStringMaker();

            //Header for imports and class naming.
            text.AppendLine("from pygments.lexer import RegexLexer, bygroups");
            text.AppendLine("from pygments.token import *");
            text.AppendLine("import re");
            text.AppendLine("__all__ =['" + data.Name + "Lexer']");
            text.AppendLine();
            text.AppendLine("class " + data.Name + "Lexer(RegexLexer):");
            text.TabIn();

            //Name with capital first letter, aliases.
            text.AppendLine("name = '" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'");
            text.AppendLine("aliases = ['" + data.Name + "']");

            //File names.
            string fNames = "[";

            foreach (var ext in data.FileExtensions)
            {
                fNames += "'" + ext + "', ";
            }
            fNames = fNames.TrimEnd(',', ' ') + "]";
            text.AppendLine(fNames);

            //Template flags.
            text.AppendLine("flags = re.MULTILINE | re.UNICODE");
            text.AppendLine();

            //Open the tokens map.
            text.AppendLine("tokens = {");
            text.TabIn();

            //Get the root context and evaluate.
            var rootCtx = data.Contexts.FirstOrDefault(x => x.Name == "main");

            if (rootCtx == null)
            {
                Error.Compile("No 'main' context exists to create the root grammar state from.");
                return(null);
            }
            AddContext(rootCtx, data, ref text);
            includedThisRun = new List <string>();

            //Evaluate the rest of the contexts.
            foreach (var context in data.Contexts)
            {
                //Ignore main, already done.
                if (context.Name == "main")
                {
                    continue;
                }

                //Add, reset includes.
                AddContext(context, data, ref text);
                includedThisRun = new List <string>();
            }

            //Add queued contexts.
            for (int i = 0; i < queuedContexts.Count; i++)
            {
                var queued = queuedContexts.ElementAt(i);
                AddQueuedContext(queued.Key.Item2, queued.Key.Item1, queued.Value, data, ref text);
            }

            text.TabOut();
            text.AppendLine("}");

            return(new CompileResult()
            {
                GeneratedFile = text.ToString(),
                Target = Target.Pygments
            });
        }
예제 #12
0
 public CompileResult Compile(IroPrecompileData data)
 {
     throw new System.NotImplementedException();
 }
예제 #13
0
        /// <summary>
        /// Compiles a set of Iro precompile data into a generated file.
        /// </summary>
        public CompileResult Compile(IroPrecompileData data)
        {
            var text = new StringBuilder();

            //Add the header.
            text.AppendLine("/*");
            text.AppendLine("* To try in Ace editor, copy and paste into the mode creator");
            text.AppendLine("*here : http://ace.c9.io/tool/mode_creator.html");
            text.AppendLine("*/");
            text.AppendLine();
            text.AppendLine("define(function(require, exports, module) {");
            text.AppendLine("\"use strict\";");
            text.AppendLine("var oop = require(\"../lib/oop\");");
            text.AppendLine("var TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;");
            text.AppendLine("/* --------------------- START ----------------------------- */");
            text.AppendLine("var MysampleHighlightRules = function() {");
            text.AppendLine("this.$rules = { ");

            //Define the main ruleset.
            var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main");

            if (mainCtx == null)
            {
                Error.Compile("No 'main' context exists to create patterns from.");
                return(null);
            }

            //Add the main context.
            AddContext(mainCtx, "start", data, ref text);

            //Add all other contexts.
            foreach (var context in data.Contexts)
            {
                //Ignore main, already processed.
                if (context.Name == "main")
                {
                    continue;
                }

                AddContext(context, context.Name, data, ref text);
            }

            //Add the queued contexts from inline pushes.
            while (queuedContexts.Count > 0)
            {
                AddQueuedContext(queuedContexts.First().Key, queuedContexts.First().Value, data, ref text);
                queuedContexts.Remove(queuedContexts.First().Key);
            }

            //Trim the trailing ",".
            text = text.TrimEnd(',');

            //Close the set.
            text.AppendLine("};");
            text.AppendLine("this.normalizeRules();");
            text.AppendLine("};");

            //Footer.
            text.AppendLine("/* ------------------------ END ------------------------------ */");
            text.AppendLine("oop.inherits(MysampleHighlightRules, TextHighlightRules);");
            text.AppendLine("exports.MysampleHighlightRules = MysampleHighlightRules;");
            text.AppendLine("});");

            return(new CompileResult()
            {
                GeneratedFile = text.ToString(),
                Target = Target.Ace
            });
        }
예제 #14
0
        public CompileResult Compile(IroPrecompileData data)
        {
            string text = "";

            //Loop over styles and remove weird proprietary Iro colour values (WhyYYYYY)
            foreach (var style in data.Styles)
            {
                ReplaceIroColours(ref style.Colour);
                ReplaceIroColours(ref style.BackgroundColour);
            }

            //Loop over styles, generate.
            foreach (var style in data.Styles)
            {
                //Name of the CSS class.
                if (!style.Name.StartsWith("."))
                {
                    Error.CompileWarning("When compiling for CSS, style names should start with a '.', prepending.");
                    text += ".";
                }

                text += style.Name + " {";

                //Body.
                if (style.Colour == null)
                {
                    Error.Compile("When compiling for CSS, all styles must have a 'color' or 'colour' property.");
                    return(null);
                }
                if (!validHexColour.IsMatch(style.Colour) && !validColours.Contains(style.Colour.ToLower()))
                {
                    Error.Compile("Invalid colour name given for style '" + style.Name + "', must be a valid CSS colour or hexadecimal colour value.");
                    return(null);
                }
                text += " color:" + style.Colour + "; ";

                //Is there a background colour?
                if (style.BackgroundColour != null)
                {
                    //Valid?
                    if (!validHexColour.IsMatch(style.Colour) && !validColours.Contains(style.Colour.ToLower()))
                    {
                        Error.Compile("Invalid background colour given for style '" + style.BackgroundColour + "', must be a valid CSS colour or hexadecimal colour value.");
                        return(null);
                    }

                    text += "background-color: " + style.BackgroundColour + "; ";
                }

                //Font stylings.s
                if (style.Bold)
                {
                    text += "font-weight: bold; ";
                }
                if (style.Italic)
                {
                    text += "font-style: italic; ";
                }

                //Close the style! :)
                text += "}\r\n";
            }

            //Done compiling, return target.
            return(new CompileResult()
            {
                Target = Target.CSS,
                GeneratedFile = text
            });
        }
예제 #15
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);
                }
            }
        }
예제 #16
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;
            }
        }
예제 #17
0
        //Adds an inline push context member.
        private void AddILPContext(string ctxName, string name, InlinePushContextMember mem, IroPrecompileData data, ref RubyStringMaker text)
        {
            //Create the rule, reset includes.
            includedThisRun = new List <string>();
            text.AppendLine("state:" + name);
            text.TabIn();

            //Add the pop rule.
            string popRule = "rule /" + mem.PopData + "/";
            var    styles  = GetPatternStyles(mem.PopStyles, data);

            if (styles.Count > 1)
            {
                //Append.
                popRule += " do";
                text.AppendLine(popRule);
                text.TabIn();

                //Newline with groups.
                popRule = "groups ";
                foreach (var scope in styles)
                {
                    popRule += scope.PygmentsScope.Replace(".", "::") + ", ";
                }
                popRule = popRule.TrimEnd(' ', ',');
                text.AppendLine(popRule);
                text.AppendLine("push :pop!");

                text.TabOut();
                text.AppendLine("end");
            }
            else if (styles.Count == 1)
            {
                //Single style.
                popRule += ", " + styles[0].PygmentsScope.Replace(".", "::") + ", :pop!";
                text.AppendLine(popRule);
            }
            else
            {
                Error.Compile("No pop styles included for pop rule '" + mem.PopData + "'.");
                return;
            }

            //Loop over rules, add them.
            foreach (var member in mem.Patterns)
            {
                AddContextMember(member, ctxName, data, ref text);
            }

            text.TabOut();
            text.AppendLine("end");
        }
예제 #18
0
        //Adds a queued context to the text.
        private void AddQueuedContext(string name, string originalCtx, InlinePushContextMember ilp, IroPrecompileData data, ref PyStringMaker text)
        {
            //Open the context.
            text.AppendLine("'" + name + "' : [");
            text.TabIn();

            //Add the pop rule.
            var popStyles = GetPatternStyles(ilp.PopStyles, data);

            text.AppendLine("(u'" + ilp.PopData.Replace("\\", "\\\\") + "', byGroups(" + string.Join(", ", popStyles.Select(x => x.PygmentsScope)).TrimEnd(',', ' ') + "), '" + originalCtx + "')");

            //Add context members.
            includedThisRun = new List <string>();
            foreach (var member in ilp.Patterns)
            {
                AddContextMember(name, member, data, ref text);
            }
            text.TrimEnd(',', ' ');

            text.TabOut();
            text.AppendLine("],");
        }
예제 #19
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("}");
            }
        }
예제 #20
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;
            }
        }