public void FindsParentMember()
        {
            var parentscope = new Sharp_LR35902_Compiler.Scope();

            parentscope.AddMember(TestMember);
            var chiledscope = new Sharp_LR35902_Compiler.Scope(parentscope);

            Assert.IsNotNull(chiledscope.GetMember("test"));
        }
        private static VariableMember getVariable(string name, Scope scope)
        {
            var existingvariable = scope.GetMember(name);

            if (existingvariable == null)
            {
                throw new SyntaxException($"Varible {name} does not exist in the current scope.");
            }

            return(existingvariable);
        }
 public VariableMember GetMember(string name) => GetLocalMember(name) ?? ParentScope?.GetMember(name);
        public static BlockNode CreateAST(IList <Token> tokens, BlockNode rootnode, ref int i, Scope previousScope)
        {
            var currentnode = rootnode;

            var currentscope = new Scope(previousScope);

            for (; i < tokens.Count; i++)
            {
                var token = tokens[i];

                if (token.Type == Variable)
                {
                    // Variable[++/--] or Variable = [Variable/Immediate]
                    var nexttoken = tokens[++i];
                    if (nexttoken.Type != Operator)
                    {
                        throw new SyntaxException("Expected operator after variable");
                    }

                    Token          valuenode;
                    VariableMember assignedvariable;
                    switch (nexttoken.Value)
                    {
                    case "=":
                        i++;
                        var expression = CreateExpression(tokens, currentscope, ref i);
                        if (expression == null)
                        {
                            throw new SyntaxException($"Unknown expression after =");
                        }

                        getVariable(token.Value, currentscope);                                 // Check it exists
                        //var existingvariable = currentscope.GetMember(token.Value);
                        //var immediatedatatype = GetImmedateDataType(expression);
                        //checkCanConvertTypes(immediatedatatype, existingvariable.DataType);
                        currentnode.AddChild(new VariableAssignmentNode(token.Value, expression));
                        i--;

                        break;

                    case "++":
                        currentnode.AddChild(new IncrementNode(token.Value));
                        break;

                    case "--":
                        currentnode.AddChild(new DecrementNode(token.Value));
                        break;

                    case "+=":
                        assignedvariable = getVariable(token.Value, currentscope);

                        valuenode = tokens[++i];
                        if (valuenode.Type == Variable)
                        {
                            var valuevariable = getVariable(valuenode.Value, currentscope);
                            currentnode.AddChild(new AdditionAssignmentNode(assignedvariable.Name, new VariableValueNode(valuevariable.Name)));
                        }
                        else if (valuenode.Type == Immediate)
                        {
                            var expr = CreateExpression(tokens, currentscope, ref i);
                            i--;
                            currentnode.AddChild(new AdditionAssignmentNode(assignedvariable.Name, new ShortValueNode(expr)));
                        }

                        break;

                    case "-=":
                        assignedvariable = getVariable(token.Value, currentscope);

                        valuenode = tokens[++i];
                        if (valuenode.Type == Variable)
                        {
                            var valuevariable = getVariable(valuenode.Value, currentscope);
                            currentnode.AddChild(new SubtractionAssignmentNode(assignedvariable.Name, new VariableValueNode(valuevariable.Name)));
                        }
                        else if (valuenode.Type == Immediate)
                        {
                            var exp = CreateExpression(tokens, currentscope, ref i);
                            i--;
                            currentnode.AddChild(new SubtractionAssignmentNode(assignedvariable.Name, new ShortValueNode(exp)));
                        }

                        break;

                    default: throw new SyntaxException("Expected operator");
                    }
                }
                else if (token.Type == DataType)
                {
                    // DataType Variable = [Variable/Immediate]
                    var variabletoken = tokens[++i];
                    if (variabletoken.Type != Variable)
                    {
                        throw new SyntaxException("Expected variable name after data type");
                    }

                    var variabledatatype = BuiltIn.DataTypes.Get(token.Value);
                    if (variabledatatype == null)
                    {
                        throw new SyntaxException($"Datatype {token.Value} does not exist.");
                    }

                    var operatornode = tokens[++i];
                    if (operatornode.Value == ";" || operatornode.Value == "=")
                    {
                        if (currentscope.GetMember(variabletoken.Value) != null)
                        {
                            throw new SyntaxException($"Variable {variabletoken.Value} already exists in the current scope.");
                        }

                        currentnode.AddChild(new VariableDeclarationNode(token.Value, variabletoken.Value));

                        if (operatornode.Value == ";")                           // Just a decleration
                        {
                            currentnode.AddChild(new VariableAssignmentNode(variabletoken.Value, new ShortValueNode(0)));
                            currentscope.AddMember(new VariableMember(variabledatatype, variabletoken.Value));
                            continue;
                        }
                    }

                    if (operatornode.Value != "=")
                    {
                        throw new SyntaxException("Expected token '='");
                    }

                    var valuenode  = tokens[++i];
                    var expression = CreateExpression(tokens, currentscope, ref i);
                    if (expression == null)
                    {
                        throw new SyntaxException($"Unexpected symbol on variable assignment '{valuenode.Value}'");
                    }
                    i--;
                    //var immediatedatatype = GetImmedateDataType(expression);
                    //checkCanConvertTypes(immediatedatatype, variabledatatype);
                    currentnode.AddChild(new VariableAssignmentNode(variabletoken.Value, expression));
                    currentscope.AddMember(new VariableMember(variabledatatype, variabletoken.Value));
                }
                else if (token.Type == ControlFlow)
                {
                    switch (token.Value)
                    {
                    case "while": break;

                    case "do": break;

                    case "for": break;

                    case "return": break;

                    case "continue": break;

                    case "else": break;

                    case "if":
                        if (tokens[i + 1].Value != "(")
                        {
                            throw new SyntaxException("Expected expression after IF statement.");
                        }

                        i += 2;
                        var expression = CreateExpression(tokens, currentscope, ref i);

                        if (tokens[i].Value != "{")
                        {
                            throw new SyntaxException("Expected open block after IF statement.");
                        }

                        i++;
                        var iftrue    = CreateAST(tokens, new BlockNode(), ref i, currentscope);
                        var iffalse   = new BlockNode();
                        var elsetoken = tokens.Get(++i);
                        if (elsetoken?.Value == "else")
                        {
                            iffalse = CreateAST(tokens, iffalse, ref i, currentscope);
                        }

                        currentnode.AddChild(new IfNode(expression, iftrue, iffalse));
                        break;

                    case "goto":
                        var nextnode = tokens[++i];
                        if (nextnode.Type != Variable)
                        {
                            throw new SyntaxException("Expected label name after goto statement.");
                        }
                        currentnode.AddChild(new GotoNode(nextnode.Value));
                        break;

                    default:                             // Label
                        var colonindex = token.Value.IndexOf(':');
                        currentnode.AddChild(new LabelNode(token.Value.Substring(0, colonindex)));
                        break;
                    }
                }
                else if (token.Value == "*")
                {
                    var addresstoken = tokens[++i];
                    if (addresstoken.Type != Immediate)
                    {
                        throw new SyntaxException("Expected address after pointer.");
                    }
                    var address = ParseImmediate(addresstoken.Value);

                    var equals = tokens[++i];
                    if (equals.Value != "=")
                    {
                        throw new SyntaxException("Expected assignment after memory address.");
                    }

                    i++;
                    var value = CreateExpression(tokens, currentscope, ref i);
                    currentnode.AddChild(new MemoryAssignmentNode(address, value));
                }
                else if (token.Value == "}")
                {
                    return(rootnode);
                }
            }

            return(rootnode);
        }