private Expression ToExpression(byte[] bytes, Prg prg, int offset = 0,
                                        FileVersion version = FileVersion.Current, bool isTrace = false)
        {
            var expressions = GetExpressions(bytes, prg, ref offset, FileVersion, isTrace: isTrace);

            if (offset != bytes.Length || expressions.Count != 1)
            {
                Debug.WriteLine($@"Bad part:
    bytes: {DebugUtilities.CompareBytes(bytes, bytes, onlyDif: false, toText: false)}
    offset: {offset}
    bytes.Length: {bytes.Length}
    expressions: {expressions.Count}
    ");
            }

            //One expression
            if (expressions.Count == 1)
            {
                return(expressions[0]);
            }

            return(null);
        }
        private List <Expression> GetExpressions(byte[] bytes, Prg prg, ref int offset,
                                                 FileVersion version = FileVersion.Current, LINE_TOKEN lineToken = 0,
                                                 bool isTrace        = false)
        {
            if (isTrace)
            {
                Debug.WriteLine("----------------------------");
                Debug.WriteLine(DebugUtilities.CompareBytes(bytes, bytes,
                                                            onlyDif: false, toText: false, offset: offset));
            }

            var expressions = new List <Expression>();

            while (offset < bytes.Length)
            {
                var byteType = ProgramCodeUtilities.GetByteType(bytes, offset);

                if (byteType == ProgramCodeUtilities.ByteType.Variable)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsVariable {offset}");
                    }
                    var expression = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Line)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsLine {offset}");
                    }
                    var token           = (LINE_TOKEN)bytes.ToByte(ref offset);
                    var lineExpressions = GetExpressions(bytes, prg, ref offset, version, token, isTrace);
                    var expression      = lineExpressions.Count > 1 ? new BinaryExpression(
                        lineExpressions[0],
                        lineExpressions[1],
                        (TYPE_TOKEN)token, FileVersion) :
                                          lineExpressions[0];
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Function)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsFunction {offset}");
                    }
                    var token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    if ((byte)token == (byte)LINE_TOKEN.STOP)
                    {
                        var variable   = new VariableExpression(bytes, prg, ref offset, FileVersion);
                        var expression = new UnaryExpression(variable, (TYPE_TOKEN)LINE_TOKEN.STOP, version);

                        expressions.Add(expression);
                    }
                    else if (expressions.Count == 0)
                    {
                        Debug.WriteLine("expressions.Count = 0");
                        var temp = 0;
                        offset -= 1;
                        expressions.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));
                        expressions.AddRange(
                            GetExpressions(bytes.ToBytes(ref offset, 3), prg, ref temp, FileVersion, lineToken));

                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, TYPE_TOKEN.DELIMITER, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var expression = new FunctionExpression(token, FileVersion, expressions.ToArray());
                        expressions.Clear();
                        expressions.Add(expression);
                    }
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Expression)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsExpression {offset}");
                    }
                    var type = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    if (ProgramCodeUtilities.IsBinaryExpression(type))
                    {
                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var lastExpression = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new UnaryExpression(lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                }
                else
                {
                    break;
                }
            }

            if (isTrace)
            {
                Debug.WriteLine($"Result: {expressions.Count} expressions. Line token: {lineToken}");
                for (var i = 0; i < expressions.Count; ++i)
                {
                    Debug.WriteLine($"Expression {i + 1}: {expressions[i].ToString()}");
                }
                Debug.WriteLine("----------------------------");
                Debug.WriteLine("");
            }

            return(expressions);
        }