예제 #1
0
 /// <summary>
 /// Sets the current node's value and it's left child
 /// </summary>
 public void Insert(String value, Node leftNode)
 {
     CurrentNode.Value = value;
     CurrentNode.Left = new Node();
     CurrentNode.Right = new Node();
     CurrentNode.Left = leftNode;
     CurrentNode = CurrentNode.Right;
 }
예제 #2
0
        /// <summary>
        /// Returns a cloned node with all the same properties
        /// </summary>
        public Node Clone()
        {
            Node clone = new Node();
            clone.Left = Left;
            clone.Right = Right;
            clone.Value = Value;
            clone.Attributes = Attributes;

            return clone;
        }
예제 #3
0
        /// <summary>
        /// Given a node, deletes all the children
        /// </summary>
        public static void DeleteTree(Node Root)
        {
            if (Root.Left != null)
                DeleteTree(Root.Left);

            if (Root.Right != null)
                DeleteTree(Root.Right);

            Root = null;
        }
예제 #4
0
        /// <summary>
        /// Outputs the parse tree in a readable format
        /// </summary>
        public static void DisplayTree(Node node, String inner)
        {
            if (node == null)
                return;

            Console.Write(inner + ">" + node.Value);

            String Attrib = "";

            foreach (String Attribute in node.Attributes)
                if (Attribute != "")
                    Attrib += " " + Attribute;

            if (Attrib != "" && node.Value != "STATEMENTS")
                Console.Write("  (Attributes: " + Attrib + ")");

            Console.Write("\n");

            DisplayTree(node.Left, inner + "-");
            DisplayTree(node.Right, inner + "-");
        }
예제 #5
0
        /// <summary>
        /// Traverses the tree in post-order (bottom-up) and optimises any conditions
        /// </summary>
        private void OptimiseConditionalsOfNode(Node currentNode)
        {
            if (currentNode.Left != null)
            {
                OptimiseConditionalsOfNode(currentNode.Left);
            }

            if (currentNode.Right != null)
            {
                OptimiseConditionalsOfNode(currentNode.Right);
            }

            if (Parser.IsConditionalOperator(currentNode.Attributes[0]))
            {
                //If left node and right node are both values
                Int32 leftValue;
                Int32 rightValue;
                if (currentNode.Left != null && Int32.TryParse(currentNode.Left.Value, out leftValue) &&
                    currentNode.Right != null && Int32.TryParse(currentNode.Right.Value, out rightValue) &&
                    currentNode.Left.Attributes[1] == "VALUE" && currentNode.Right.Attributes[1] == "VALUE")
                {
                    if (currentNode.Attributes[0] == "==")
                        currentNode.Value = (leftValue == rightValue ? 1 : 0).ToString();
                    else if (currentNode.Attributes[0] == "<=")
                        currentNode.Value = (leftValue <= rightValue ? 1 : 0).ToString();
                    else if (currentNode.Attributes[0] == ">=")
                        currentNode.Value = (leftValue >= rightValue ? 1 : 0).ToString();
                    else
                        currentNode.Value = (leftValue != rightValue ? 1 : 0).ToString();

                    currentNode.Attributes[1] = "VALUE";
                    currentNode.Attributes[0] = currentNode.Attributes[2] = "";
                    currentNode.Left = null;
                    currentNode.Right = null;
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Parse a new statement
        /// </summary>
        private Node ParseStatement(Node node, ref Node currentNodeMarker)
        {
            //Call appropriate parse function according to first Token in the statement

            if (VariableTypes.Contains(GetCurrentToken().Value))
                node = DeclareVariable(node);
            else if (GetCurrentToken().Value.Equals("INPUT"))
                node = ParseInputFunction(node);
            else if (GetCurrentToken().Value.Equals("PRINT"))
                node = ParsePrintFunction(node);
            else if (GetCurrentToken().Type.Equals(TokenType.Identifier) && Tokens[TokenIndex+1].Value.Equals("="))
                node = AssignExpression(node);
            else if (GetCurrentToken().Value.Equals("IF"))
                node = ParseIfStatement(node, ref currentNodeMarker);
            else
            {
                Console.WriteLine("INVALID STATEMENT on line " + GetCurrentToken().Line + ": " + GetCurrentToken().Value);
                node = null;
            }

            return node;
        }
예제 #7
0
        /// <summary>
        /// <PRINT> ::= 'PRINT', ( <IDENTIFIER> | <CONSTANT> );
        /// </summary>
        private Node ParsePrintFunction(Node node)
        {
            node = new Node();
            node.Value = "PRINT";
            TokenIndex++;
            CheckIfOutOfTokens();
            node.Attributes[0] = GetCurrentToken().Value;

            //Semantic part
            //Check for validity - argument should be variable or constant
            if (!GetCurrentToken().Type.Equals(TokenType.Identifier) && !GetCurrentToken().Type.Equals(TokenType.String)
                && !GetCurrentToken().Type.Equals(TokenType.Number))
                Console.Write("Invalid argument for PRINT statement");
            //And in case of variable, it must exist
            if (GetCurrentToken().Type.Equals(TokenType.Identifier) && !VariableExists(GetCurrentToken().Value))
                Console.Write("Undeclared variable name used as argument in PRINT");

            //Store some attributes to aid in code gen
            if (GetCurrentToken().Type.Equals(TokenType.Number) ||
                GetVariableType(GetCurrentToken().Value).Equals(VariableType.Integer))
                node.Attributes[1] = "INT";
            else
                node.Attributes[1] = "STRING";

            if (GetCurrentToken().Type.Equals(TokenType.Identifier))
                node.Attributes[2] = "VARIABLE";
            else
                node.Attributes[2] = "VALUE";

            TokenIndex++;

            return node;
        }
예제 #8
0
        /// <summary>
        /// <INPUT> ::= 'INPUT', <IDENTIFIER>
        /// </summary>
        private Node ParseInputFunction(Node node)
        {
            node = new Node();
            node.Value = "INPUT";
            TokenIndex++;
            CheckIfOutOfTokens();
            node.Attributes[0] = GetCurrentToken().Value;

            //Semantic part
            if (!GetCurrentToken().Type.Equals(TokenType.Identifier))
                Console.WriteLine("Invalid argument for input statement");

            if (!VariableExists(GetCurrentToken().Value))
                Console.WriteLine("Undeclared variable name used as argument in INPUT");

            if (GetVariableType(GetCurrentToken().Value).Equals(VariableType.Integer))
                node.Attributes[1] = "INT";
            else
                node.Attributes[1] = "STRING";

            TokenIndex++;

            return node;
        }
예제 #9
0
        /// <summary>
        /// <IFSTATEMENT> := 'IF (' <CONDITION> ')' <STATEMENTS> 'END'
        /// If statements within if statements do not work
        /// </summary>
        private Node ParseIfStatement(Node node, ref Node currentNodeMarker)
        {
            node = new Node();

            node.Value = "IF";

            TokenIndex++;

            //Semantics
            if (!GetCurrentToken().Value.Equals("("))
                Console.Write("Enclose the condition in (...)");

            TokenIndex++;

            //Parse the condition in the left child of the IF node
            node.Left = ParseCondition(node.Left);

            //Semantics
            if (!GetCurrentToken().Value.Equals(")"))
                Console.Write("Enclose the condition in (...)");

            //Skip the right bracket and new line
            TokenIndex++;
            TokenIndex++;

            //Create a root class node for the top of the IF tree
            Root root = new Root();
            //Insert the IF node in the root
            root.Insert(node.Value, node.Left);

            //Mark the current node and set it
            currentNodeMarker = node.Right;
            Node currentNode = node.Right;

            //Parse statements until END is found
            while (!GetCurrentToken().Value.Equals("END"))
            {
                if (GetCurrentToken().Type.Equals(TokenType.EOL))
                {
                    TokenIndex++;
                }
                //Insert the statements in
                currentNode = ParseStatement(currentNode, ref currentNodeMarker);

                if (currentNode != null)
                {
                    root.Insert("STATEMENTS", currentNode);
                    currentNode = currentNode.Right;
                    currentNodeMarker = currentNode;
                }

                TokenIndex++;
            }

            //The final right node will always be empty, so remove it
            root.NullifyEmptyChildren();

            return (Node)root;
        }
예제 #10
0
        /// <summary>
        /// Parse a facor in an expression
        /// EBNF: <factor> ::= <IDENTIFIER> | <CONSTANT> | ( ‘(’, <expression>, ‘)’ ) | ( '-', <factor> );
        /// We need to have the node where the factor is to be held
        /// A the type so we know whether we are expecting an int or a string
        /// </summary>
        private Node ParseFactor(Node node, VariableType type)
        {
            //Check if we have any tokens left
            CheckIfOutOfTokens();

            //First check for a parenthesised expression
            //( ‘(’, <expression>, ‘)’ )
            if (GetCurrentToken().Value.Equals("("))
            {
                //Skip the parenthesis
                TokenIndex++;

                //Get the expression
                node = ParseExpression(node, type);

                if (!GetCurrentToken().Value.Equals(")"))
                    Console.WriteLine("Expected closing bracket");

                //Skip the closing paren
                TokenIndex++;

                return node;
            }

            //If it's not a parenthesised expression
            //Check for a negative number
            //( '-', <factor> )
            if (type.Equals(VariableType.Integer))
            {
                if (GetCurrentToken().Value.Equals("-"))
                {
                    TokenIndex++;
                    node = ParseFactor(node, type);

                    //Apply the negative sign to the parsed factor
                    node.Value = "-" + node.Value;
                    return node;
                }
            }

            //We have narrowed it down to either a <IDENTIFIER> or <CONSTANT>
            node = new Node();

            //Store the value in the node
            node.Value = GetCurrentToken().Value;

            //Semantics - check if variable exists
            if (GetCurrentToken().Type.Equals(TokenType.Identifier) && !VariableExists(GetCurrentToken().Value))
                Console.WriteLine("Undeclared variable");

            //Give the node extra info to aid in code gen
            if (GetCurrentToken().Type.Equals(TokenType.Identifier))
                node.Attributes[0] = "VARIABLE";
            else
                node.Attributes[1] = "VALUE";

            TokenIndex++;

            return node;
        }
예제 #11
0
        /// <summary>
        /// To declare a variable
        /// In EBNF:
        /// 	         <DECLARE> ::= ( 'INT' | 'STRING' | 'BOOL'), <IDENTIFIER>;
        /// </summary>
        private Node DeclareVariable(Node node)
        {
            node = new Node();
            node.Value = "DECLARE";
            node.Attributes[1] = GetCurrentToken().Value;
            TokenIndex++;
            CheckIfOutOfTokens();
            node.Attributes[0] = GetCurrentToken().Value;

            //Semantics - check variable name is valid
            if (!GetCurrentToken().Type.Equals(TokenType.Identifier) || IsNewVariableNameInvalid(GetCurrentToken().Value))
                Console.WriteLine("Invalid variable name used in declaration");

            //Add the variable to the list for future reference
            var varInfo = new VariableInfo();
            varInfo.Name = GetCurrentToken().Value;

            varInfo.Type = GetVariableFromValue(node.Attributes[1]);

            Variables.Add(varInfo);

            TokenIndex++;

            return node;
        }
예제 #12
0
        /// <summary>
        /// To assign expression to a varibale
        /// In EBNF:
        ///	       <ASSIGN> ::= <IDENTIFIER>, '=', <EXPRESSION>;
        /// </summary>
        private Node AssignExpression(Node node)
        {
            node.Value = "ASSIGN";

            node.Left = new Node();
            node.Left.Value = GetCurrentToken().Value;

            //Skip through '=' symbol
            TokenIndex += 2;

            node.Right = ParseExpression(node.Right, GetVariableType(node.Left.Value));

            //Semantics - checks variable exists
            if (!VariableExists(node.Left.Value))
                Console.WriteLine("Undeclared var name used in assignment");

            //Additional node information to aid code gen
            if (GetVariableType(node.Left.Value).Equals(VariableType.Integer))
                node.Attributes[0] = "INT";
            else if (GetVariableType(node.Left.Value).Equals(VariableType.Boolean))
                node.Attributes[0] = "BOOL";
            else
                node.Attributes[0] = "STRING";

            return node;
        }
예제 #13
0
 /// <summary>
 /// Inserts the final node in the parse tree
 /// </summary>
 public void InsertFinal(Node node)
 {
     CurrentNode.Value = "STATEMENTS";
     CurrentNode.Left = node;
 }
예제 #14
0
 public Root()
 {
     CurrentNode = this;
 }
예제 #15
0
        /// <summary>
        /// Recursively searches through the child nodes 
        /// </summary>
        public void NullifyEmptyChildren()
        {
            if (Left != null)
            {
                Left.NullifyEmptyChildren();

                if (Left.IsEmpty())
                    Left = null;
            }

            if (Right != null)
            {
                Right.NullifyEmptyChildren();

                if (Right.IsEmpty())
                    Right = null;
            }
        }
예제 #16
0
        /// <summary>
        /// To parse a term in the epression
        /// In EBNF: <term> ::= <factor>, { ‘*’|’/’, <factor> };
        /// </summary>
        private Node ParseTerm(Node node)
        {
            CheckIfOutOfTokens();

            //Parse the first factor
            node = ParseFactor(node, VariableType.Integer);

            //Then the {...}
            //For each * or / parse another factor
            while (GetCurrentToken().Value.Equals("*") || GetCurrentToken().Value.Equals("/"))
            {
                Node clonedNode = node.Clone();
                node.Left = clonedNode;
                node.Value = GetCurrentToken().Value;
                TokenIndex++;
                node.Right = ParseFactor(node.Right, VariableType.Integer);
            }

            return node;
        }
예제 #17
0
        /// <summary>
        /// Parses all the tokens
        /// </summary>
        public void ParseProgram()
        {
            //Last Token must be EOL so add one in case
            Token eol = new Token();
            eol.Line = Tokens[Tokens.Count - 1].Line + 1;
            eol.Type = TokenType.EOL;
            eol.Value = "\n";
            Tokens.Add(eol);

            //Start at the first Token
            TokenIndex = 0;

            for (int line = 0; line < LineCount && GetCurrentToken() != null; line++)
            {

                Node currentNode = new Node();
                Node currentNodeMarker;

                if (!GetCurrentToken().Type.Equals(TokenType.EOL))
                {
                    currentNodeMarker = null;

                    if (line == LineCount - 1)
                    {
                        currentNode = ParseStatement(currentNode, ref currentNodeMarker);
                        RootNode.InsertFinal(currentNode);

                        if (currentNodeMarker != null)
                            RootNode.CurrentNode = currentNodeMarker;
                    }
                    else
                    {
                        RootNode.Insert("STATEMENTS", ParseStatement(currentNode, ref currentNodeMarker));

                        if (currentNodeMarker != null)
                            RootNode.CurrentNode = currentNodeMarker;
                    }
                }

                TokenIndex++;
            }

            RootNode.NullifyEmptyChildren();
        }
예제 #18
0
        /// <summary>
        /// Parses a condition
        /// EBNF: <condition> ::= <expression> | <expression> '==' <expression>
        /// </summary>
        private Node ParseCondition(Node node)
        {
            node = new Node();
            node.Value = "CONDITION";

            //LHS of condition
            node.Left = ParseExpression(node, VariableType.Integer);

            //Check for anything that isn't a variable or value
            //If we don't find either, the condition has been parsed
            if (!GetCurrentToken().Type.Equals(TokenType.Identifier) && !GetCurrentToken().Type.Equals(TokenType.Number)
                && !IsConditionalOperator(GetCurrentToken().Value))
                return node;

            //Get the equality comparators
            node.Attributes[0] = GetCurrentToken().Value;

            TokenIndex++;

            //Get the RHS of the condition
            node.Right = ParseExpression(node, VariableType.Integer);

            return node;
        }
예제 #19
0
        /// <summary>
        /// Traverses the tree in post-order (bottom-up) and optimises any arithmetic
        /// </summary>
        private void OptimiseOperatorsAndValuesOfNode(Node currentNode)
        {
            if (currentNode.Left != null)
            {
                OptimiseOperatorsAndValuesOfNode(currentNode.Left);
            }

            if (currentNode.Right != null)
            {
                OptimiseOperatorsAndValuesOfNode(currentNode.Right);
            }

            if ("+-*/".Contains(currentNode.Value))
            {
                //If left node and right node are both values
                Int32 leftValue;
                Int32 rightValue;
                if (currentNode.Left != null && Int32.TryParse(currentNode.Left.Value, out leftValue) &&
                    currentNode.Right != null && Int32.TryParse(currentNode.Right.Value, out rightValue) &&
                    currentNode.Left.Attributes[1] == "VALUE" && currentNode.Right.Attributes[1] == "VALUE")
                {
                    if (currentNode.Value == "+")
                        currentNode.Value = (leftValue + rightValue).ToString();
                    else if (currentNode.Value == "-")
                        currentNode.Value = (leftValue - rightValue).ToString();
                    else if (currentNode.Value == "*")
                        currentNode.Value = (leftValue * rightValue).ToString();
                    else
                        currentNode.Value = (leftValue / rightValue).ToString();

                    currentNode.Attributes[1] = "VALUE";
                    currentNode.Attributes[0] = currentNode.Attributes[2] = "";
                    currentNode.Left = null;
                    currentNode.Right = null;
                }
            }
        }
예제 #20
0
        /// <summary>
        /// To parse the expression
        /// In EBNF: <expression> ::= <term>, { ‘+’|’-’, <term> };
        /// </summary>
        private Node ParseExpression(Node node, VariableType type)
        {
            CheckIfOutOfTokens();

            //A numeric expr can be made up of terms, but a string expr is made up of string factors only
            //(we can't multilply, divide or subtract strings)
            if (type.Equals(VariableType.Integer))
                node = ParseTerm(node);
            else if (type.Equals(VariableType.Boolean))
                node = ParseCondition(node);
            else
                node = ParseFactor(node, VariableType.String);

            //While a valid operator is found
            while (GetCurrentToken().Value.Equals("+") || (type.Equals(VariableType.Integer) &&
                                                           GetCurrentToken().Value.Equals("-")))
            {
                if (node == null)
                    node = new Node();

                Node clonedNode = node.Clone();
                node.Left = clonedNode;
                node.Value = GetCurrentToken().Value;
                TokenIndex++;

                if (type.Equals(VariableType.Integer))
                    node.Right = ParseTerm(node.Right);
                else
                    node.Right = ParseFactor(node.Right, VariableType.String);
            }

            return node;
        }