예제 #1
0
    private List <Node> GenerateNode(List <string> lines, Vector2 startPoint, ref int index, Transform parent, bool inBody)
    {
        index++;
        var nodes = new List <Node>();
        var line  = lines[index];

        if (line == KeyWords.begin.ToString() || line == KeyWords.initialization.ToString())
        {
            List <Node> newNodes;
            while ((newNodes = GenerateNode(lines, startPoint, ref index, parent, true)) != null)
            {
                nodes.AddRange(newNodes);
                if (newNodes.Any())
                {
                    startPoint = new Vector2(startPoint.x, newNodes.Last().GetBottom().y) + new Vector2(0, -g_Margin);
                }
            }
        }
        else if (line == KeyWords.end.ToString() || line == KeyWords.end + ".")
        {
            return(null);
        }
        else if (line.StartsWith("function ") || line.StartsWith("procedure "))
        {
            var fNode = parent.AppendNew(Prefabs.FuncNode, startPoint - Prefabs.FuncNode.Offset);
            fNode.Index = index;
            line        = line.TrimString("function").TrimString("procedure").Trim();
            fNode.Name  = line.Cut(0, line.IndexOf('(') - 1);
            fNode.Text  = "Начало <" + fNode.Name + ">";

            do
            {
                int sPos = lines[index].IndexOf("(") + 1;
                int ePos = lines[index].IndexOf(")");
                fNode.Args.Add(lines[index].Cut(sPos, ePos == -1 ? lines[index].Length - 1 : ePos - 1));
            }while (lines[index++].IndexOf(")") == -1);


            while (lines[index] != KeyWords.begin.ToString())
            {
                fNode.Vars.Add(lines[index].TrimString("vars").Trim(')', '(', ' '));
                index++;
            }
            index--;
            fNode.children.AddRange(GenerateNode(lines, (Vector2)fNode.transform.position + new Vector2(0, fNode.ExitPoint.y - g_Margin), ref index, fNode.transform, true));

            var endNode = fNode.transform.AppendNew(Prefabs.BeginEndNode, fNode.GetBottom() - Prefabs.FuncNode.Offset);
            endNode.Text = "Конец";
            fNode.children.Add(endNode);

            nodes.Add(fNode);
        }
        else if (line.StartsWithAny(KeyWords.@if))
        {
            var IfNode = parent.AppendNew(Prefabs.IfNode, startPoint - Prefabs.IfNode.Offset);
            IfNode.Index     = index;
            IfNode.Condition = line.Remove(0, 2).Trim(' ');
            IfNode.TrueNodes.AddRange(GenerateNode(lines, (Vector2)IfNode.transform.position + new Vector2(IfWidth / 2, IfNode.ExitPoint.y - g_Margin), ref index, parent, true));
            if (lines[index + 1] == "else")
            {
                index++;
                IfNode.FalseNodes.AddRange(GenerateNode(lines, (Vector2)IfNode.transform.position + new Vector2(IfNode.TrueNodes.Any(x => x is IfNode) ? -IfWidth : -IfWidth / 2, IfNode.ExitPoint.y - g_Margin), ref index, parent, true));
                if (IfNode.FalseNodes.Any(x => x is IfNode))
                {
                    IfNode.TrueNodes.ForEach(x => x.Translate(new Vector2(IfWidth / 2, 0)));
                }

                if (IfNode.TrueNodes.Any() && IfNode.FalseNodes.Any())
                {
                    var d = -IfNode.TrueNodes.Min(x => x.GetWidthLimits().x) + IfNode.FalseNodes.Max(x => x.GetWidthLimits().y);
                    if (d > 0)
                    {
                        IfNode.TrueNodes.ForEach(x => x.Translate(new Vector2(d / 2 + UIController.MarginLineDistance, 0)));
                        IfNode.FalseNodes.ForEach(x => x.Translate(new Vector2(-d / 2 - UIController.MarginLineDistance, 0)));
                    }
                }
            }
            nodes.Add(IfNode);
            _lastCodeNode = null;
        }
        else if (line.StartsWithAny(KeyWords.@while))
        {
            var WhileNode = parent.AppendNew(Prefabs.WhileNode, startPoint - Prefabs.WhileNode.Offset);
            WhileNode.Index     = index;
            WhileNode.Condition = line.Remove(0, 5).Trim(' ');
            WhileNode.children.AddRange(GenerateNode(lines, (Vector2)WhileNode.transform.position + new Vector2(0, WhileNode.ExitPoint.y - g_Margin), ref index, parent, true));
            nodes.Add(WhileNode);
            _lastCodeNode = null;
        }
        else if (line.StartsWith(KeyWords.repeat))
        {
            var WhileNode = parent.AppendNew(Prefabs.RepeatNode, startPoint - Prefabs.WhileNode.Offset);
            WhileNode.Index = index;
            List <Node> newNodes;
            while ((newNodes = GenerateNode(lines, startPoint, ref index, parent, true)) != null)
            {
                WhileNode.children.AddRange(newNodes);
                if (newNodes.Any())
                {
                    startPoint = new Vector2(startPoint.x, newNodes.Last().GetBottom().y) + new Vector2(0, -g_Margin);
                }

                if (newNodes.LastOrDefault() is UntilNode)
                {
                    break;
                }
            }
            nodes.Add(WhileNode);
        }
        else if (line.StartsWithAny(KeyWords.until))
        {
            var untilNode = parent.AppendNew(Prefabs.UntilNode, startPoint - Prefabs.WhileNode.Offset);
            line = line.Remove(0, 5).Trim();
            untilNode.Condition = line;
            nodes.Add(untilNode);
            _lastCodeNode = null;
        }
        else if (line.StartsWithAny(KeyWords.@for))
        {
            var ForNode = parent.AppendNew(Prefabs.ForNode, startPoint - Prefabs.ForNode.Offset);
            ForNode.Index     = index;
            ForNode.Condition = line.Remove(0, 3).Trim(' ');
            ForNode.children.AddRange(GenerateNode(lines, (Vector2)ForNode.transform.position + new Vector2(0, ForNode.ExitPoint.y - g_Margin), ref index, parent, true));
            nodes.Add(ForNode);
            _lastCodeNode = null;
        }
        else if (line.StartsWith("write(") || line.StartsWith("read(") || line.StartsWith("writeln(") || line.StartsWith("readln(") || line == "writeln" || line == "write" || line == "read" || line == "readln")
        {
            if (_lastCodeNode != null && _lastCodeNode.EndIndex == index - 1 && _lastCodeNode.GetType() == typeof(IONode))
            {
                _lastCodeNode.EndIndex = index;
                _lastCodeNode.Text    += "\n" + line + ";";
                if (_lastCodeNode.EndIndex - _lastCodeNode.Index > MaxNodeLinesCount)
                {
                    _lastCodeNode = null;
                }
            }
            else
            {
                _lastCodeNode          = parent.AppendNew(Prefabs.IONode, startPoint - Prefabs.CodeNode.Offset);
                _lastCodeNode.Index    = index;
                _lastCodeNode.EndIndex = index;
                _lastCodeNode.Text     = line + ";";
                nodes.Add(_lastCodeNode);
            }
        }
        else if (line.StartsWithAny(KeyWords.var) && !inBody)
        {
            VarNode vNode = parent.AppendNew(Prefabs.VarNode, startPoint - Prefabs.VarNode.Offset);
            vNode.Index    = index;
            vNode.EndIndex = index;
            vNode.AddVar(line.Remove(0, 3).Trim());
            while (!lines[index + 1].StartsWithAny(KeyWords.begin, KeyWords.uses, KeyWords.function, KeyWords.procedure, KeyWords.type, KeyWords.@const)) //while (lines[index+1].ContainsAny("begin", "uses", "function", "procedure", "type") == null)
            {
                vNode.AddVar(lines[index + 1]);
                index++;
            }
            nodes.Add(vNode);
        }
        else if (line.StartsWithAny(KeyWords.except))
        {
            var exceptNode = parent.AppendNew(Prefabs.IfNode, startPoint - Prefabs.WhileNode.Offset);
            exceptNode.Index     = index;
            exceptNode.Condition = "{exception occured}";
            List <Node> node;
            while ((node = GenerateNode(lines, (Vector2)exceptNode.transform.position + new Vector2(0, exceptNode.ExitPoint.y - g_Margin), ref index, parent, true)) != null)
            {
                exceptNode.TrueNodes.AddRange(node);
            }
            nodes.Add(exceptNode);
            _lastCodeNode = null;
        }
        else if (line.StartsWithAny(KeyWords.@const))
        {
            ConstNode vNode = parent.AppendNew(Prefabs.ConstNode, startPoint - Prefabs.VarNode.Offset);
            vNode.Index    = index;
            vNode.EndIndex = index;
            vNode.AddVar(line.Remove(0, 5).Trim());
            while (!lines[index + 1].StartsWithAny()) //while (lines[index+1].ContainsAny("begin", "uses", "function", "procedure", "type") == null)
            {
                vNode.AddVar(lines[index + 1]);
                index++;
            }
            nodes.Add(vNode);
        }
        else if (line.StartsWithAny(KeyWords.uses))
        {
            line = line.Remove(0, 4);
            try
            {
                foreach (var lib in line.Split(',').Select(x => x.Trim()))
                {
                    int    inChar   = lib.IndexOf(" in ");
                    string fileName = lib + ".pas";
                    if (inChar != -1)
                    {
                        int l1 = lib.IndexOf("@%");
                        int l2 = lib.IndexOf("%@");
                        if (l1 != -1 && l2 > l1)
                        {
                            fileName = Literals[int.Parse(lib.Cut(l1 + 2, l2 - 1))].Trim(' ', '.', '\'', '/', (char)92);
                        }
                    }

                    print(fileName);
                    if (System.IO.File.Exists(fileName))
                    {
                        string code           = System.IO.File.ReadAllText(fileName);
                        string finCode        = null;
                        int    implementation = code.IndexOf("implementation");
                        code = code.Remove(0, implementation + "implementation".Length);
                        int finalization = code.IndexOf("finalization");
                        int codeLen      = code.Length;
                        if (finalization != -1)
                        {
                            finCode = code.Remove(0, finalization + "finalization".Length);
                            code    = code.Substring(0, finalization) + "end.";
                        }
                        //print(code);
                        var parsed = ParseCode(code);
                        var unit   = GenerateUnit(parsed, ref startPoint, ref TopPoint, lib.Split()[0]);
                        if (unit.Any())
                        {
                            nodes.AddRange(unit);
                            var joint = parent.AppendNew(Prefabs.JointNode, new Vector2(startPoint.x, unit.Last().GetBottom().y));
                            nodes.Add(joint);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogException(e);
            }
        }
        else if (line.StartsWithAny(KeyWords.type, KeyWords.program))
        {
        }
        else
        {
            var function = Functions.Any() ? line.ContainsAny(Functions.Keys) : null;
            if (function != null)
            {
                FunctionCallNode node = parent.AppendNew(Prefabs.FunctionCallNode, startPoint - Prefabs.CodeNode.Offset);
                node.Index    = index;
                node.Text     = line + ";";
                node.Function = Functions[function];
                nodes.Add(node);
            }
            else
            {
                if (_lastCodeNode != null && _lastCodeNode.EndIndex == index - 1 && _lastCodeNode.GetType() == typeof(CodeNode))
                {
                    _lastCodeNode.EndIndex = index;
                    _lastCodeNode.Text    += "\r\n" + line + ";";
                    if (_lastCodeNode.EndIndex - _lastCodeNode.Index > MaxNodeLinesCount)
                    {
                        _lastCodeNode = null;
                    }
                }
                else
                {
                    _lastCodeNode          = parent.AppendNew(Prefabs.CodeNode, startPoint - Prefabs.CodeNode.Offset);
                    _lastCodeNode.Index    = index;
                    _lastCodeNode.EndIndex = index;
                    _lastCodeNode.Text     = line + ";";
                    nodes.Add(_lastCodeNode);
                }
            }
        }
        return(nodes);
    }