Exemple #1
0
 public BracketedSection(BracketedSection parent, BracketType bracketType)
 {
     _codeFragment = new StringBuilder();
     BracketType   = bracketType;
     Children      = new List <BracketedSection>();
     Parent        = parent;
 }
Exemple #2
0
        public BracketedSection AppendChild(BracketType bracketType)
        {
            var childBracketSection = new BracketedSection(this, bracketType);

            Children.Add(childBracketSection);

            return(childBracketSection);
        }
Exemple #3
0
        public ByondCode(string dmFolder)
        {
            var rootNode = "root";

            _codeTreeRoot = new NTree <string>(rootNode);

            var files = Directory.GetFiles(dmFolder, "*.dm", SearchOption.AllDirectories);

            var codeLines = new List <string>(600000);

            foreach (var file in files)
            {
                codeLines.AddRange(File.ReadAllLines(file));
            }

            Debug.Log(codeLines.Count);

            Debug.Log("PREPROCESSING BYOND CODE");

            var bracketedCode           = new BracketedSection(null, BracketType.None);
            var currentBracketedSection = bracketedCode;

            for (var i = 0; i < codeLines.Count; i++)
            {
                linesToProcess--;
                if (linesToProcess <= 0)
                {
                    break;
                }

                var line          = codeLines[i];
                var lastCharacter = ' ';
                var wasANonBlankCharacterFoundInLine = false;
                var isFirstNonBlankCharacterInLine   = false;
                var isThisCharacterEscaped           = false;

                while (!bracketedCode.IsRoot &&
                       (currentBracketedSection.NonTextBracketType == BracketType.SingleLineComment ||
                        currentBracketedSection.NonTextBracketType == BracketType.PreprocessorDirective))
                {
                    //End of line reset single-line comment and preprocessor directives
                    currentBracketedSection = currentBracketedSection.GetNonTextParent();
                }

                for (var j = 0; j < line.Length; j++)
                {
                    var currentCharacter = line[j];

                    if (isFirstNonBlankCharacterInLine)
                    {
                        isFirstNonBlankCharacterInLine = false;
                    }

                    if (!wasANonBlankCharacterFoundInLine && currentCharacter != '\t' && currentCharacter != ' ')
                    {
                        wasANonBlankCharacterFoundInLine = true;
                        isFirstNonBlankCharacterInLine   = true;
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.SingleLineComment)
                    {
                        //No way to close a single-line comment until next row
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (isThisCharacterEscaped)
                    {
                        isThisCharacterEscaped  = false;
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = ' ';
                        continue;
                    }

                    if (currentCharacter == '\\')
                    {
                        if (currentBracketedSection.NonTextBracketType == BracketType.MultiLineComment ||
                            currentBracketedSection.NonTextBracketType == BracketType.StringUnlocked ||
                            currentBracketedSection.NonTextBracketType == BracketType.FilePath)
                        {
                            isThisCharacterEscaped  = true;
                            currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                            lastCharacter           = ' ';
                            continue;
                        }
                    }

                    if (!bracketedCode.IsRoot)
                    {
                        switch (currentBracketedSection.NonTextBracketType)
                        {
                        case BracketType.None:
                            break;

                        case BracketType.Regular:
                            if (currentCharacter == ')')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.Square:
                            if (currentCharacter == ']')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.Curly:
                            if (currentCharacter == '}')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.SingleLineComment:
                            break;

                        case BracketType.MultiLineComment:
                            if (lastCharacter == '*' && currentCharacter == '/')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.StringUnlocked:
                            if (currentCharacter == '"')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.StringLocked:
                            if (currentCharacter == '@')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.FilePath:
                            if (currentCharacter == '\'')
                            {
                                currentBracketedSection = currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.MultiLineString:
                            if (lastCharacter == '"' && currentCharacter == '}')
                            {
                                currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                                currentBracketedSection = currentBracketedSection.GetNonTextParent();
                                lastCharacter           = ' ';
                                currentCharacter        = ' ';
                                continue;
                            }

                            break;

                        case BracketType.PreprocessorDirective:
                        case BracketType.Text:
                            break;

                        default:
                            throw new Exception("Unknown BracketType: " + currentBracketedSection.NonTextBracketType);
                        }
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.MultiLineComment)
                    {
                        //In a multi-line comment, no other bracket types can be opened from this until it's closed
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.StringLocked)
                    {
                        //Cannot start any kind of bracket from within a string
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.FilePath)
                    {
                        //Cannot start any kind of bracket from within a string
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (currentCharacter == '[')
                    {
                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.Square);
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.StringUnlocked)
                    {
                        //Cannot start any kind of bracket from within a string
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.MultiLineString)
                    {
                        //Cannot start any kind of bracket from within a string
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (isFirstNonBlankCharacterInLine && currentCharacter == '#')
                    {
                        //Preprocessor directive can only start if the # is the first character in a line
                        currentBracketedSection =
                            currentBracketedSection.AppendChild(BracketType.PreprocessorDirective);
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (lastCharacter == '/' && currentCharacter == '/')
                    {
                        //Start of a single-line comment
                        //bracketedCode.Last.Value.CodeFragment.Remove(bracketedCode.Last.Value.CodeFragment.Length - 1,
                        //    1);
                        //if (bracketedCode.Last.Value.CodeFragment.Length == 0)
                        //{
                        //    bracketedCode.RemoveLast();
                        //}

                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.SingleLineComment);
                        currentBracketedSection = currentBracketedSection.AppendChar(lastCharacter);
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (lastCharacter == '/' && currentCharacter == '*')
                    {
                        //Start of a multi-line comment
                        //bracketedCode.Last.Value.CodeFragment.Remove(bracketedCode.Last.Value.CodeFragment.Length - 1,
                        //    1);
                        //if (bracketedCode.Last.Value.CodeFragment.Length == 0)
                        //{
                        //    bracketedCode.RemoveLast();
                        //}

                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.MultiLineComment);
                        currentBracketedSection = currentBracketedSection.AppendChar(lastCharacter);
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    if (currentBracketedSection.NonTextBracketType == BracketType.PreprocessorDirective)
                    {
                        //Cannot start strings, (, [ or { brackets from within a preprocessor directive
                        currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                        lastCharacter           = currentCharacter;
                        continue;
                    }

                    switch (currentCharacter)
                    {
                    case '(':
                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.Regular);
                        break;

                    case '{':
                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.Curly);
                        break;

                    case '"':
                        if (lastCharacter == '{')
                        {
                            //bracketedCode.Last.Value.CodeFragment.Remove(
                            //    bracketedCode.Last.Value.CodeFragment.Length - 1, 1);
                            //if (bracketedCode.Last.Value.CodeFragment.Length == 0)
                            //{
                            //    if (currentBracketedSection.BracketType == BracketType.Curly)
                            //    {
                            //        //Remove curly bracket which may have been set when the previous character ({) was encountered
                            //        currentBracketedSection = currentBracketedSection.Parent;
                            //    }
                            //
                            //    bracketedCode.RemoveLast();
                            //}

                            currentBracketedSection =
                                currentBracketedSection.AppendChild(BracketType.MultiLineString);
                            currentBracketedSection = currentBracketedSection.AppendChar(lastCharacter);
                        }
                        else
                        {
                            currentBracketedSection =
                                currentBracketedSection.AppendChild(BracketType.StringUnlocked);
                        }

                        break;

                    case '\'':
                        currentBracketedSection = currentBracketedSection.AppendChild(BracketType.FilePath);
                        break;

                    case '@':
                        if (lastCharacter == '@')
                        {
                            //bracketedCode.Last.Value.CodeFragment.Remove(
                            //    bracketedCode.Last.Value.CodeFragment.Length - 1, 1);
                            //if (bracketedCode.Last.Value.CodeFragment.Length == 0)
                            //{
                            //    bracketedCode.RemoveLast();
                            //}

                            currentBracketedSection = currentBracketedSection.AppendChild(BracketType.StringLocked);
                            currentBracketedSection = currentBracketedSection.AppendChar(lastCharacter);
                        }

                        break;

                    case '[':
                    case '/':
                    case '*':
                    case '#':
                        //handled before this block
                        break;

                    default:
                        //regular character, move along, nothing to see here
                        break;
                    }

                    currentBracketedSection = currentBracketedSection.AppendChar(currentCharacter);
                    lastCharacter           = currentCharacter;
                }

                currentBracketedSection = currentBracketedSection.AppendChar('\n');
            }

            var logFileLocation = Application.persistentDataPath + @"\BracketedByondCode0.txt";

            for (var i = 0; i < 1000; i++)
            {
                logFileLocation = Application.persistentDataPath + @"\BracketedByondCode" + i + ".txt";
                if (!File.Exists(logFileLocation))
                {
                    break;
                }
            }

            using (var file = new StreamWriter(logFileLocation))
            {
                file.Write(bracketedCode.ToString());
            }

            Debug.Log("Bracket Log File Saved: " + logFileLocation);
            Debug.Log("DONE PREPROCESSING BYOND CODE");

            return;

            var tabStack             = new Stack <List <string> >();
            var currentIndentNode    = _codeTreeRoot;
            var isInMultiLineComment = false;

            StringBuilder lineResolutionDescriptor = new StringBuilder();

            for (var i = 0; i < codeLines.Count; i++)
            {
                lineResolutionDescriptor.Clear();
                lineResolutionDescriptor.AppendLine("Line = " + codeLines[i]);
                linesToProcess--;
                if (linesToProcess <= 0)
                {
                    Debug.Log("End processing code lines");
                    break;
                }

                linesProcessed.AppendLine(codeLines[i]);

                //Remove one-line comments
                var code = Regex.Replace(codeLines[i], @"\/\/.*$", "");

                //Remove multi-line comments starting and ending on the same line
                code = Regex.Replace(code, @"\/\*[\s\S]*?\*\/", "");

                if (!isInMultiLineComment)
                {
                    //Begin multi-line comment if /* detected
                    if (code.Contains(@"/*"))
                    {
                        code = Regex.Replace(code, @"\/\*.*", "");
                        isInMultiLineComment = true;
                    }
                }
                else
                {
                    //End multi-line comment if */ detected
                    if (code.Contains(@"*/"))
                    {
                        code = Regex.Replace(code, @".*\*\/", "");
                        isInMultiLineComment = false;
                    }
                    else
                    {
                        //Line is in a multi-line comment, which doesn't end in it. There is no code here.
                        code = "";
                    }
                }

                lineResolutionDescriptor.AppendLine("Code = " + code);

                lineResolutionDescriptor.AppendLine("Current Node: " + currentIndentNode.Data);
                lineResolutionDescriptor.AppendLine("TabStack Before: ");
                lineResolutionDescriptor.AppendLine(TabStackToString(tabStack));

                if (code.Trim().Length == 0)
                {
                    lineResolutionDescriptor.AppendLine("RESOLUTION = BLANK LINE");
                    lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                    PrintLineLog(lineResolutionDescriptor);
                    continue;
                }

                var lineTabIndent = CountTabs(code);

                var codeWithoutTabs = code.TrimStart();

                if (codeWithoutTabs.StartsWith("#"))
                {
                    //TODO preprocessor directives
                    lineResolutionDescriptor.AppendLine("RESOLUTION = PREPROCESSOR");
                    lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                    PrintLineLog(lineResolutionDescriptor);
                    continue;
                }

                if (lineTabIndent > tabStack.Count)
                {
                    if (codeWithoutTabs.StartsWith("/"))
                    {
                        //Incorrect definition of hierarchy, tab is suddenly bigger than before
                        lineResolutionDescriptor.AppendLine("TabIndent = BIGGER (Error); " + lineTabIndent + " == " +
                                                            tabStack.Count);
                        lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                        PrintLineLog(lineResolutionDescriptor);
                        throw new Exception("Tab indent for line bigger than previous: " + lineTabIndent + " > " +
                                            tabStack.Count + "; Line: " + code);
                    }
                    else
                    {
                        //todo Plain line of code with bigger indent  (if, loops, switch, etc)
                        lineResolutionDescriptor.AppendLine("RESOLUTION = PLAIN LINE OF CODE");
                        lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                        PrintLineLog(lineResolutionDescriptor);
                    }
                }
                else if (lineTabIndent == tabStack.Count)
                {
                    lineResolutionDescriptor.AppendLine("TabIndent = EQUAL; " + lineTabIndent + " == " +
                                                        tabStack.Count);
                }
                else if (lineTabIndent < tabStack.Count)
                {
                    lineResolutionDescriptor.AppendLine("TabIndent = LOWER; " + lineTabIndent + " < " + tabStack.Count);
                    var safety = 100;
                    var tabStackIndentIndex = 0;
                    var currentCodeTreePath = new List <string>();
                    var tabStackList        = tabStack.ToList();
                    tabStackList.Reverse();
                    while ((safety > 0) && (tabStackIndentIndex != lineTabIndent))
                    {
                        try
                        {
                            currentCodeTreePath.AddRange(tabStackList[tabStackIndentIndex]);
                        }
                        catch (Exception e)
                        {
                            lineResolutionDescriptor.AppendLine("ERROR! tabStackIndentIndex = " + tabStackIndentIndex);
                            lineResolutionDescriptor.AppendLine(TabStackToString(tabStack));
                        }

                        tabStackIndentIndex++;

                        safety--;
                        if (safety <= 1)
                        {
                            lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                            PrintLineLog(lineResolutionDescriptor);
                            throw new Exception("Infinite loop detected in ByondCode constructor: Pos 1");
                        }
                    }

                    safety = 100;
                    while ((safety > 0) && (tabStackIndentIndex != tabStack.Count))
                    {
                        tabStack.Pop();

                        safety--;
                        if (safety <= 1)
                        {
                            lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                            PrintLineLog(lineResolutionDescriptor);
                            throw new Exception("Infinite loop detected in ByondCode constructor: Pos 2");
                        }
                    }

                    currentIndentNode = _codeTreeRoot;
                    for (var codePartIndex = 0; codePartIndex < currentCodeTreePath.Count; codePartIndex++)
                    {
                        currentIndentNode = MoveToChild(currentIndentNode, currentCodeTreePath[codePartIndex]);
                    }
                }

                lineResolutionDescriptor.AppendLine("TabStack After trim: ");
                lineResolutionDescriptor.AppendLine(TabStackToString(tabStack));

                if (codeWithoutTabs.StartsWith("/"))
                {
                    lineResolutionDescriptor.AppendLine("TabStack expansion detected: " + code);
                    var codePartsWithLeadingBlank = codeWithoutTabs.Split('/');

                    var codeParts = codePartsWithLeadingBlank.ToList();
                    codeParts.RemoveAt(0);

                    for (var codePartIndex = 0; codePartIndex < codeParts.Count; codePartIndex++)
                    {
                        currentIndentNode = MoveToChild(currentIndentNode, codeParts[codePartIndex]);
                    }

                    tabStack.Push(codeParts);

                    lineResolutionDescriptor.AppendLine("TabStack After expansion: ");
                    lineResolutionDescriptor.AppendLine(TabStackToString(tabStack));
                }
                else
                {
                    //TODO plain line of code
                    lineResolutionDescriptor.AppendLine("RESOLUTION = PLAIN LINE OF CODE");
                }

                lineResolutionDescriptor.AppendLine("CODE TREE = " + _codeTreeRoot.ToString());
                PrintLineLog(lineResolutionDescriptor);
            }

            UnityEngine.Debug.Log(linesToProcess.ToString());
            UnityEngine.Debug.Log(_codeTreeRoot.ToString());
        }