コード例 #1
0
        public ICodeNode Parse(Token token)
        {
            token = InternalScanner.GetNextToken(); // consume the REPEAT

            // create the LOOP and TEST nodes.
            ICodeNode loop_node = ICodeFactory.CreateICodeNode(ICodeNodeType.LOOP);
            ICodeNode test_node = ICodeFactory.CreateICodeNode(ICodeNodeType.TEST);

            // parse the statement list terminated by the UNTIL token.
            // the LOOP node is the parent of the statement subtrees.
            StatementParser stmnt_parser =
                StatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            stmnt_parser.ParseList(token, loop_node, TokenType.UNTIL, ErrorCode.MISSING_UNTIL);
            token = InternalScanner.CurrentToken;

            // parse the expression.
            // the TEST node adopts the expression subtree as its only child.
            // the LOOP node adopts the TEST node.
            ExpressionParser expr_parser =
                ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            test_node.Add(expr_parser.Parse(token));
            loop_node.Add(test_node);

            return loop_node;
        }
コード例 #2
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
        public ICodeNode Parse(Token token)
        {
            Token tok = InternalScanner.GetNextToken(); // consume the CASE token

            // create a SELECT node
            ICodeNode select_node = ICodeFactory.CreateICodeNode(ICodeNodeType.SELECT);

            // parse the CASE expression.
            // the SELECT node adopts the expression subtree as its first child.
            ExpressionParser expr_parser =
                ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            select_node.Add(expr_parser.Parse(tok));

            tok = InternalScanner.CurrentToken;

            // synchronize the OF token.
            tok = Parser.Synchronize(OF_SET, InternalScanner, this);
            if (tok.TokenType == TokenType.OF)
            {
                tok = InternalScanner.GetNextToken(); // consume the OF
            } else
            {
                ErrorHandler.Flag(tok, ErrorCode.MISSING_OF, this);
            }

            // set of CASE branch constants.
            HashSet<object> constant_set = new HashSet<object>();

            // loop to parse each CASE branch until the END token
            // or the end of the source file.
            while (!tok.IsEof && tok.TokenType != TokenType.END)
            {
                // the SELECT node adopts the CASE branch subtree
                select_node.Add(ParseBranch(tok, constant_set));

                tok = InternalScanner.CurrentToken;
                if (tok.TokenType == TokenType.SEMICOLON)
                {
                    tok = InternalScanner.GetNextToken(); // consume the ;
                } else if (CONSTANT_START_SET.Contains(tok.TokenType))
                {
                    ErrorHandler.Flag(tok, ErrorCode.MISSING_SEMICOLON, this);
                }
            }

            // look for the END token.
            if (tok.TokenType == TokenType.END)
            {
                tok = InternalScanner.GetNextToken(); // consume the END
            } else
            {
                ErrorHandler.Flag(tok, ErrorCode.MISSING_END, this);
            }

            return select_node;
        }
コード例 #3
0
ファイル: ErrorHandler.cs プロジェクト: jstark/dradis
        public static void Flag(Token token, ErrorCode err, message.MessageProducer mp)
        {
            var args = Tuple.Create(token.LineNumber, token.Position, token.Lexeme, err.Message);
               Message msg = new Message(MessageType.SyntaxError, args);
               mp.Send(msg);

               if (++errors > MAX_ERRORS)
               {
               AbortTranslation(ErrorCode.TOO_MANY_ERRORS, mp);
               }
        }
コード例 #4
0
        public ICodeNode Parse(Token token)
        {
            Contract.Requires(token.TokenType == TokenType.BEGIN);
            // ignore argument !
            token = InternalScanner.GetNextToken();

            // create the COMPOUND node.
            ICodeNode compound_node = ICodeFactory.CreateICodeNode(ICodeNodeType.COMPOUND);

            // parse the statement list terminated by the END token.
            StatementParser statement_parser = StatementParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
            statement_parser.ParseList(token, compound_node, TokenType.END, ErrorCode.MISSING_END);
            return compound_node;
        }
コード例 #5
0
ファイル: StatementParser.cs プロジェクト: jstark/dradis
        public ICodeNode Parse(Token token)
        {
            ICodeNode node;
            switch (token.TokenType)
            {
                case TokenType.BEGIN:
                    CompoundStatementParser cmpnd_parser =
                        CompoundStatementParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
                    node = cmpnd_parser.Parse(token);
                    break;
                case TokenType.IDENTIFIER:
                    AssignmentStatementParser assign_parser =
                        AssignmentStatementParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
                    node = assign_parser.Parse(token);
                    break;
                case TokenType.REPEAT:
                    RepeatStatementParser repeat_parser =
                        RepeatStatementParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
                    node = repeat_parser.Parse(token);
                    break;
                case TokenType.WHILE:
                    WhileStatementParser while_parser =
                        WhileStatementParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
                    node = while_parser.Parse(token);
                    break;
                case TokenType.FOR:
                    ForStatementParser for_parser =
                        ForStatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
                    node = for_parser.Parse(token);
                    break;
                case TokenType.IF:
                    IfStatementParser if_parser =
                        IfStatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
                    node = if_parser.Parse(token);
                    break;
                case TokenType.CASE:
                    CaseStatementParser case_parser =
                        CaseStatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
                    node = case_parser.Parse(token);
                    break;
                default:
                    node = ICodeFactory.CreateICodeNode(ICodeNodeType.NO_OP);
                    break;
            }

            // set the current line number as an attribute.
            SetLineNumber(node, token.LineNumber);
            return node;
        }
コード例 #6
0
        public ICodeNode Parse(Token token)
        {
            // create the ASSIGN node
            ICodeNode assign_node = ICodeFactory.CreateICodeNode(ICodeNodeType.ASSIGN);

            // lookup up the target identifier in the symbol table stack.
            // enter the identifier into the table if it's not found.
            string target_name = token.Lexeme.ToLower();
            SymbolTableEntry target_id = SymTabStack.FindInLocal(target_name);
            if (target_id == null)
            {
                target_id = SymTabStack.CreateInLocal(target_name);
            }
            target_id.AppendLine(token.LineNumber);

            Contract.Requires(token.TokenType == TokenType.IDENTIFIER);
            token = InternalScanner.GetNextToken(); // consume the identifier token

            // create the variable node and set its name attribute.
            ICodeNode variable_node = ICodeFactory.CreateICodeNode(ICodeNodeType.VARIABLE);
            variable_node.SetAttribute(ICodeKey.ID, target_id);

            // the assign node adopts the variable node as its first child.
            assign_node.Add(variable_node);

            // synchronize on the := token.
            token = Parser.Synchronize(COLON_EQUALS_SET, InternalScanner, this);

            // look for the := token
            if (token.TokenType == TokenType.COLON_EQUALS)
            {
                token = InternalScanner.GetNextToken(); // consume the :=
            } else
            {
                ErrorHandler.Flag(token, ErrorCode.MISSING_COLON_EQUALS, this);
            }

            // parse the expression. The ASSIGN node adopts the expression's node
            // as its second child.
            ExpressionParser exp_parser = ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, observers);
            assign_node.Add(exp_parser.Parse(token));

            return assign_node;
        }
コード例 #7
0
ファイル: IfStatementParser.cs プロジェクト: jstark/dradis
        public ICodeNode Parse(Token token)
        {
            Token tok = InternalScanner.GetNextToken(); // consume the IF token

            // create an IF node.
            ICodeNode if_node = ICodeFactory.CreateICodeNode(ICodeNodeType.IF);

            // parse the expression.
            // the IF node adopts the expression subtree as its first child.
            ExpressionParser expr_parser =
                ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            if_node.Add(expr_parser.Parse(tok));

            // synchronize the THEN
            tok = Parser.Synchronize(THEN_SET, InternalScanner, this);
            if (tok.TokenType == TokenType.THEN)
            {
                tok = InternalScanner.GetNextToken(); // consume the THEN
            } else
            {
                ErrorHandler.Flag(tok, ErrorCode.MISSING_THEN, this);
            }

            // parse the THEN statement.
            // the IF node adopts the statement subtree as its second child.
            StatementParser stmt_parser =
                StatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            if_node.Add(stmt_parser.Parse(tok));
            tok = InternalScanner.CurrentToken;

            // look for an ELSE
            if (tok.TokenType == TokenType.ELSE)
            {
                tok = InternalScanner.GetNextToken(); // consume the THEN token

                // parse the ELSE statement.
                // the IF node adopts the statement subtree as its third child.
                if_node.Add(stmt_parser.Parse(tok));
            }

            return if_node;
        }
コード例 #8
0
ファイル: WhileStatementParser.cs プロジェクト: jstark/dradis
        public ICodeNode Parse(Token token)
        {
            token = InternalScanner.GetNextToken(); // consume the WHILE

            // create LOOP, TEST and NOT nodes
            ICodeNode loop_node = ICodeFactory.CreateICodeNode(ICodeNodeType.LOOP);
            ICodeNode break_node = ICodeFactory.CreateICodeNode(ICodeNodeType.TEST);
            ICodeNode not_node = ICodeFactory.CreateICodeNode(ICodeNodeType.NOT);

            // the LOOP node adopts the TEST node as its first child.
            // the TEST node adopts the NOT node as its only child.
            loop_node.Add(break_node);
            break_node.Add(not_node);

            ExpressionParser expr_parser =
                ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            not_node.Add(expr_parser.Parse(token));

            // synchronize at the DO.
            token = Parser.Synchronize(DO_SET, InternalScanner, this);
            if (token.TokenType == TokenType.DO)
            {
                token = InternalScanner.GetNextToken();
            } else
            {
                ErrorHandler.Flag(token, ErrorCode.MISSING_DO, this);
            }

            // parse the statement
            // the LOOP node adopts the statement subtree as its second child.
            StatementParser stmnt_parser =
                StatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            loop_node.Add(stmnt_parser.Parse(token));

            return loop_node;
        }
コード例 #9
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
        private void ParseConstantList(Token token, ICodeNode constants_node, HashSet<object> constant_set)
        {
            // loop to parse each constant.
            while (CONSTANT_START_SET.Contains(token.TokenType))
            {
                // the constants list node adopts the constant node.
                constants_node.Add(ParseConstant(token, constant_set));

                // synchronize at the comma between constants.
                token = Parser.Synchronize(COMMA_SET, InternalScanner, this);

                // look for the COMMA
                if (token.TokenType == TokenType.COMMA)
                {
                    token = InternalScanner.GetNextToken(); // consume the ,
                } else if (CONSTANT_START_SET.Contains(token.TokenType))
                {
                    ErrorHandler.Flag(token, ErrorCode.MISSING_COMMA, this);
                }
            }
        }
コード例 #10
0
ファイル: StatementParser.cs プロジェクト: jstark/dradis
        public void ParseList(Token token, ICodeNode parent, TokenType terminator, ErrorCode error)
        {
            var terminator_set = new HashSet<TokenType>(STMT_START_SET);
            terminator_set.Add(terminator);

            while(!token.IsEof && token.TokenType != terminator)
            {
                // parse a statement. The parent node adopts the statement node.
                ICodeNode statement_node = Parse(token);
                parent.Add(statement_node);
                token = InternalScanner.CurrentToken;

                // look for the semicolon between the statements.
                if (token.TokenType == TokenType.SEMICOLON)
                {
                    token = InternalScanner.GetNextToken();
                }
                else if (STMT_START_SET.Contains(token.TokenType))
                {
                    ErrorHandler.Flag(token, ErrorCode.MISSING_SEMICOLON, this);
                }

                // Synchronize at the start of the next statement
                // or at the terminator.
                token = Parser.Synchronize(terminator_set, InternalScanner, this);
            }

            // look for the terminator token
            if (token.TokenType == terminator)
            {
                token = InternalScanner.GetNextToken();
            } else
            {
                ErrorHandler.Flag(token, error, this);
            }
        }
コード例 #11
0
ファイル: ExpressionParser.cs プロジェクト: jstark/dradis
 public ICodeNode Parse(Token token)
 {
     return ParseExpression(token);
 }
コード例 #12
0
ファイル: ExpressionParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseTerm(Token token)
        {
            // parse a factor and make its node the root node.
            ICodeNode root = ParseFactor(token);

            token = InternalScanner.CurrentToken;
            while (MUL_OPS.Contains(token.TokenType))
            {
                // create a new operator node and adopt the current tree
                // as its first child.
                ICodeNodeType op = MUL_OPS_OPS_MAP[token.TokenType];
                ICodeNode op_node = ICodeFactory.CreateICodeNode(op);
                op_node.Add(root);

                token = InternalScanner.GetNextToken(); // consume the operator

                // parse another factor. The operator node adopts
                // the term's tree as its second child.
                op_node.Add(ParseFactor(token));

                // the operator node becomes the new root node.
                root = op_node;
                token = InternalScanner.CurrentToken;
            }
            return root;
        }
コード例 #13
0
ファイル: ExpressionParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseSimpleExpression(Token token)
        {
            TokenType sign = TokenType.INVALID; // type of leading sign, if any

            // look for a leading + or - sign
            if (token.TokenType == TokenType.PLUS || token.TokenType == TokenType.MINUS)
            {
                sign = token.TokenType;
                token = InternalScanner.GetNextToken(); // consume + or -
            }

            // parse a term and make the root of its tree the root node/
            ICodeNode root = ParseTerm(token);

            // was there a leading - sign ?
            if (sign == TokenType.MINUS)
            {
                // create a NEGATE node and adopt the current tree
                // as its child. The NEGATE node becomes the new root node.
                ICodeNode negate = ICodeFactory.CreateICodeNode(ICodeNodeType.NEGATE);
                negate.Add(root);
                root = negate;
            }

            token = InternalScanner.CurrentToken;

            // loop over additive operators
            while (ADD_OPS.Contains(token.TokenType))
            {
                // create a new operator node and adopt the current tree as its first child
                ICodeNodeType op_type = ADD_OPS_OPS_MAP[token.TokenType];
                ICodeNode op_node = ICodeFactory.CreateICodeNode(op_type);
                op_node.Add(root);

                token = InternalScanner.GetNextToken(); // consume the operator

                // parse another term. The operator node adopts
                // the term's tree as its second child.
                op_node.Add(ParseTerm(token));

                // the operator node becomes the new root node.
                root = op_node;
                token = InternalScanner.CurrentToken;
            }
            return root;
        }
コード例 #14
0
ファイル: ExpressionParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseFactor(Token token)
        {
            ICodeNode root = null;

            switch (token.TokenType)
            {
                case TokenType.IDENTIFIER:
                    {
                        // look the identifier in the symbol table stack.
                        // flag the identifier as undefined if it's not found.
                        string name = token.Lexeme.ToLower();
                        SymbolTableEntry id = SymTabStack.Find(name);
                        if (id == null)
                        {
                            ErrorHandler.Flag(token, ErrorCode.IDENTIFIER_UNDEFINED, this);
                            id = SymTabStack.CreateInLocal(name);
                        }

                        root = ICodeFactory.CreateICodeNode(ICodeNodeType.VARIABLE);
                        root.SetAttribute(ICodeKey.ID, id);
                        id.AppendLine(token.LineNumber);
                        token = InternalScanner.GetNextToken();
                    }
                    break;
                case TokenType.INTEGER:
                    // create an INTEGER_CONSTANT node as the root node.
                    root = ICodeFactory.CreateICodeNode(ICodeNodeType.INTEGER_CONSTANT);
                    root.SetAttribute(ICodeKey.VALUE, token.Value);
                    token = InternalScanner.GetNextToken();
                    break;
                case TokenType.REAL:
                    // create a REAL_CONSTANT node as the root node.
                    root = ICodeFactory.CreateICodeNode(ICodeNodeType.REAL_CONSTANT);
                    root.SetAttribute(ICodeKey.VALUE, token.Value);
                    token = InternalScanner.GetNextToken();
                    break;
                case TokenType.STRING:
                    // create a STRING_CONSTANT node as the root node.
                    root = ICodeFactory.CreateICodeNode(ICodeNodeType.STRING_CONSTANT);
                    root.SetAttribute(ICodeKey.VALUE, token.Value);
                    token = InternalScanner.GetNextToken();
                    break;
                case TokenType.NOT:
                    token = InternalScanner.GetNextToken(); // consume NOT

                    // create a NOT node as the root node
                    root = ICodeFactory.CreateICodeNode(ICodeNodeType.NOT);

                    // parse a factor. The NOT node adopts the
                    // factor as its child.
                    root.Add(ParseFactor(token));
                    break;
                case TokenType.LEFT_PAREN:
                    token = InternalScanner.GetNextToken(); // consume the (

                    // parse an expression and make its node the root node.
                    root = ParseExpression(token);

                    // look for the matching ) token.
                    token = InternalScanner.CurrentToken;
                    if (token.TokenType == TokenType.RIGHT_PAREN)
                    {
                        token = InternalScanner.GetNextToken(); // consume the )
                    }
                    else
                    {
                        ErrorHandler.Flag(token, ErrorCode.MISSING_RIGHT_PAREN, this);
                    }
                    break;
                default:
                    ErrorHandler.Flag(token, ErrorCode.UNEXPECTED_TOKEN, this);
                    break;
            }
            return root;
        }
コード例 #15
0
ファイル: ExpressionParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseExpression(Token token)
        {
            // parse a simple expression, and make it the root of its tree
            // root node.
            ICodeNode root = ParseSimpleExpression(token);

            token = InternalScanner.CurrentToken;
            if (REL_OPS.Contains(token.TokenType))
            {
                // create a new operator node and adopt the current tree
                // as its first child.
                ICodeNodeType type = REL_OPS_MAP[token.TokenType];
                ICodeNode op_node = ICodeFactory.CreateICodeNode(type);
                op_node.Add(root);

                token = InternalScanner.GetNextToken(); // consume the operator

                // parse the second simple expression. The operator node adopts
                // the simple expression's tree as its second child.
                op_node.Add(ParseSimpleExpression(token));

                // the operator node becomes the new node
                root = op_node;
            }
            return root;
        }
コード例 #16
0
ファイル: Scanner.cs プロジェクト: jstark/dradis
 public Token GetNextToken()
 {
     CurrentToken = ExtractToken();
     return CurrentToken;
 }
コード例 #17
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseConstant(Token token, HashSet<object> constant_set)
        {
            TokenType sign = TokenType.INVALID;
            ICodeNode constant_node = null;

            // synchronize at the start of a constant.
            token = Parser.Synchronize(CONSTANT_START_SET, InternalScanner, this);
            if (token.TokenType == TokenType.PLUS || token.TokenType == TokenType.MINUS)
            {
                sign = token.TokenType;
                token = InternalScanner.GetNextToken(); // consume sign
            }

            // parse the constant.
            switch (token.TokenType)
            {
                case TokenType.IDENTIFIER:
                    constant_node = ParseIdentifierConstant(token, sign);
                    break;
                case TokenType.INTEGER:
                    constant_node = ParseIntegerConstant(token.Lexeme, sign);
                    break;
                case TokenType.STRING:
                    constant_node = ParseCharacterConstant(token, (string)token.Value, sign);
                    break;
                default:
                    ErrorHandler.Flag(token, ErrorCode.INVALID_CONSTANT, this);
                    break;
            }

            // check for reused constants
            if (constant_node != null)
            {
                object value = constant_node.GetAttribute(ICodeKey.VALUE);

                if (constant_set.Contains(value))
                {
                    ErrorHandler.Flag(token, ErrorCode.CASE_CONSTANT_REUSED, this);
                } else
                {
                    constant_set.Add(value);
                }
            }

            InternalScanner.GetNextToken(); // consume the constant
            return constant_node;
        }
コード例 #18
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseCharacterConstant(Token token, string value, TokenType sign)
        {
            ICodeNode constant_node = null;

            if (sign != TokenType.INVALID)
            {
                ErrorHandler.Flag(token, ErrorCode.INVALID_CONSTANT, this);
            } else
            {
                if (value.Length == 1)
                {
                    constant_node = ICodeFactory.CreateICodeNode(ICodeNodeType.STRING_CONSTANT);
                    constant_node.SetAttribute(ICodeKey.VALUE, value);
                } else
                {
                    ErrorHandler.Flag(token, ErrorCode.INVALID_CONSTANT, this);
                }
            }

            return constant_node;
        }
コード例 #19
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
        private ICodeNode ParseBranch(Token token, HashSet<object> const_set)
        {
            // create a SELECT_BRANCH node and a SELECT_CONSTANTS node
            // the SELECT _BRANCH adopts the SELECT_CONSTANTS node as its
            // first child.
            ICodeNode branch_node = ICodeFactory.CreateICodeNode(ICodeNodeType.SELECT_BRANCH);
            ICodeNode constant_nodes = ICodeFactory.CreateICodeNode(ICodeNodeType.SELECT_CONSTANTS);
            branch_node.Add(constant_nodes);

            // parse the list of CASE branch constants.
            // the SELECT_CONSTANTS node adopts each constant.
            ParseConstantList(token, constant_nodes, const_set);

            // look for the : token
            token = InternalScanner.CurrentToken;
            if (token.TokenType == TokenType.COLON)
            {
                token = InternalScanner.GetNextToken();
            } else
            {
                ErrorHandler.Flag(token, ErrorCode.MISSING_COLON, this);
            }

            // parse the CASE branch statement. The SELECT_BRANCH node adopts
            // the statement subtree as its second child.
            StatementParser stmnt_parser =
                StatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            branch_node.Add(stmnt_parser.Parse(token));

            return branch_node;
        }
コード例 #20
0
ファイル: CaseStatementParser.cs プロジェクト: jstark/dradis
 private ICodeNode ParseIdentifierConstant(Token token, TokenType sign)
 {
     // Placeholder! Don't allow for now.
     ErrorHandler.Flag(token, ErrorCode.INVALID_CONSTANT, this);
     return null;
 }
コード例 #21
0
ファイル: ForStatementParser.cs プロジェクト: jstark/dradis
        public ICodeNode Parse(Token token)
        {
            Token tok = InternalScanner.GetNextToken(); // consume the FOR
            Token target = tok;

            // create the COMPOUND, LOOP and TEST nodes
            ICodeNode compound = ICodeFactory.CreateICodeNode(ICodeNodeType.COMPOUND);
            ICodeNode loop = ICodeFactory.CreateICodeNode(ICodeNodeType.LOOP);
            ICodeNode test = ICodeFactory.CreateICodeNode(ICodeNodeType.TEST);

            // parse the embedded initial assignment.
            AssignmentStatementParser assign =
                AssignmentStatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            ICodeNode init_assign_node = assign.Parse(tok);

            // set the current line number
            SetLineNumber(init_assign_node, target.LineNumber);

            // the COMPOUND node adopts the initial ASSIGN and the LOOP nodes
            // as its first and second children.
            compound.Add(init_assign_node);
            compound.Add(loop);

            // synchronize at the TO or DOWNTO
            tok = Parser.Synchronize(TO_DOWNTO_SET, InternalScanner, this);
            TokenType direction = tok.TokenType;

            // look for the TO or DOWNTO
            if (tok.TokenType == TokenType.TO || tok.TokenType == TokenType.DOWNTO)
            {
                tok = InternalScanner.GetNextToken(); // consume the TO or DOWNTO
            } else
            {
                direction = TokenType.TO;
                ErrorHandler.Flag(tok, ErrorCode.MISSING_TO_DOWN_TO, this);
            }

            // create a relational operator node: GT for TO, or LT for DOWNTO
            ICodeNode relop_node =
                ICodeFactory.CreateICodeNode(direction == TokenType.TO ? ICodeNodeType.GT : ICodeNodeType.LT);

            // copy the control VARIABLE node. The relational operator node
            // adopts the copied VARIABLE node, as its first child.
            ICodeNode control_var_node = init_assign_node.GetChildren().ElementAt(0);
            relop_node.Add(control_var_node.Copy());

            // parse the termination expression. The relational operator node
            // adopts the expression as its second child.
            ExpressionParser expr_parser =
                ExpressionParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            relop_node.Add(expr_parser.Parse(tok));

            // the TEST node adopts the relational operator node as its only child.
            // the LOOP node adopts the TEST node as its first child.
            test.Add(relop_node);
            loop.Add(test);

            // synchronize at the DO.
            tok = Parser.Synchronize(DO_SET, InternalScanner, this);
            if (tok.TokenType == TokenType.DO)
            {
                tok = InternalScanner.GetNextToken();
            } else
            {
                ErrorHandler.Flag(tok, ErrorCode.MISSING_DO, this);
            }

            // parse the nested statement. The LOOP node adopts the statement
            // node as its second child.
            StatementParser stmnt_parser =
                StatementParser.CreateWithObservers(InternalScanner, SymTabStack, Observers);
            loop.Add(stmnt_parser.Parse(tok));

            // create an assignment with a copy of the control variable
            // to advance the value of the variable.
            ICodeNode next_assign = ICodeFactory.CreateICodeNode(ICodeNodeType.ASSIGN);
            next_assign.Add(control_var_node.Copy());

            // create an arithmetic operator node
            // ADD for TO, SUBTRACT for DOWNTO
            ICodeNode arith_node =
                ICodeFactory.CreateICodeNode(direction == TokenType.TO ? ICodeNodeType.ADD : ICodeNodeType.SUBTRACT);

            // the operator node adopts adopts a copy of the loop variable as its
            // first child and the value 1 as its second child.
            arith_node.Add(control_var_node.Copy());
            ICodeNode one_node = ICodeFactory.CreateICodeNode(ICodeNodeType.INTEGER_CONSTANT);
            one_node.SetAttribute(ICodeKey.VALUE, 1);
            arith_node.Add(one_node);

            // the next ASSIGN node adopts the arithmetic operator node as its
            // second child. The loop node adopts to the next ASSIGN node as its
            // third child.
            next_assign.Add(arith_node);
            loop.Add(next_assign);

            // set the current line number attribute.
            SetLineNumber(next_assign, target.LineNumber);

            return compound;
        }