示例#1
0
        protected virtual BlockNode ParseBlock(IPrimaryParentNode parent, SpecialCharacterToken leftBracket)
        {
            // PARSE: <block constructor> ::= '[' <block body> ']'
            //      <block body> ::= [<block argument>* '|'] [<temporaries>] [<statements>]
            //      <block argument> ::= ':' identifier
            BlockNode result = new BlockNode(parent, leftBracket);

            // PARSE: [<block argument>* '|']
            // ISSUE: It this a bug in X3J20. Shouldn't it be: [<block argument>+ '|']
            // The current definition allows blocks like: [ | ] ... or ... [ | self doStuff ]  ... or ... [ | | temp | temp := self something ]
            // We assume X3J20 bug and expect: [<block argument>+ '|']
            VerticalBarToken         argumentsBar = null;
            List <BlockArgumentNode> arguments    = new List <BlockArgumentNode>();

            Token token = this.GetNextTokenxx(Preference.VerticalBar | Preference.NegativeSign);

            // Check if the block has arguments
            if (Parser.IsBlockArgumentPrefix(token))
            {
                // ... yes arguments ... parse them ...
                while (true)
                {
                    if (Parser.IsBlockArgumentPrefix(token))
                    {
                        // <block argument>
                        arguments.Add(this.ParseBlockArgument(result, (SpecialCharacterToken)token));
                    }
                    else if (token is VerticalBarToken)
                    {
                        // The '|' after the arguments.
                        argumentsBar = (VerticalBarToken)token;
                        token        = this.GetNextTokenxx(Preference.NegativeSign | Preference.VerticalBar);
                        break; // Done with block arguments
                    }
                    else
                    {
                        this.ReportParserError(result, SemanticErrors.MissingBlockClosingArgsBar, token);
                        break;
                    }
                    // Get the next token
                    token = this.GetNextTokenxx(Preference.VerticalBar | Preference.NegativeSign);
                }
            }

            // PARSE: [<temporaries>]
            ParseTemporariesResult ptr = this.ParseTemporaries(result, token);

            // PARSE: <statements>
            token = this.GetNextTokenxx(Preference.NegativeSign);
            StatementNode statements = this.ParseStatement(result, token);

            // Ensure the block is properly closed.
            SpecialCharacterToken rightBracket = null;

            token = this.GetNextTokenxx(Preference.Default);
            if (!Parser.IsBlockEndDelimiter(token))
            {
                this.ReportParserError(result, SemanticErrors.MissingBlockClosingBracket, token);
                this.ResidueToken = token;
            }
            else
            {
                rightBracket = (SpecialCharacterToken)token;
            }

            result.SetContents(arguments, argumentsBar, ptr.LeftBar, ptr.Temporaries, ptr.RightBar, statements, rightBracket);
            return(result);
        }
示例#2
0
        /// <summary>
        /// Create a new cascade message sequence.
        /// </summary>
        /// <param name="parent">Parent node that defines this cascade message node.</param>
        /// <param name="token">Token representing the semicolon used to delimit cascade message sequences.</param>
        protected internal CascadeMessageSequenceNode(ICascadeMessageSequenceParentNode parent, SpecialCharacterToken token)
        {
#if DEBUG
            if (parent == null)
            {
                throw new ArgumentNullException("parent");
            }
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }
#endif
            this.Parent    = parent;
            this.Semicolon = token;
        }
示例#3
0
        protected virtual ArrayLiteralNode ParseArrayLiteral(ILiteralNodeParent parent, SpecialCharacterToken arrayToken)
        {
            // PARSE: <array literal> ::= '#(' <array element>* ')'
            // <array element> ::= <literal> | identifier

            Token token = this.GetNextTokenxx(Preference.Default);

            if (!Parser.IsOpeningParenthesis(token))
            {
                this.ReportParserError(parent, SemanticErrors.MissingLiteralArrayOpeningParenthesis, token);
                // The hash token is thrown away and lost :-/   ... only the current token is passed on.
                this.ResidueToken = token;
                return(null);
            }
            List <LiteralNode> elements = new List <LiteralNode>();
            ArrayLiteralNode   result   = new ArrayLiteralNode(parent, arrayToken, (SpecialCharacterToken)token);

            // Process tokens inside the array ...
            while (true)
            {
                // ... get next token in the array ...
                token = this.GetNextTokenxx(Preference.NegativeSign | Preference.UnquotedSelector);

                // Is this closing parenthesis?
                if (Parser.IsClosingParenthesis(token))
                {
                    // Closing parenthesis ... done with the array, return litral array node.
                    result.SetContents(elements, (SpecialCharacterToken)token);
                    this.ResidueToken = null;
                    return(result);
                }

                if (token is EofToken)
                {
                    // Unfinished source code ... return
                    result.SetContents(elements, null);
                    this.ReportParserError(parent, SemanticErrors.MissingLiteralArrayClosingParenthesis, token);
                    this.ResidueToken = token;
                    return(result);
                }

                // PARSE: <array element> ::= <literal> | identifier
                if (token is ILiteralArrayIdentifierToken)
                {
                    // identifier ... special case only inside arrays.
                    elements.Add(new IdentifierLiteralNode(result, (ILiteralArrayIdentifierToken)token));
                }
                else
                {
                    // ... it's not identifier, so it must be an literal
                    LiteralNode element = this.ParseLiteral(result, token);
                    if (element == null)
                    {
                        // Report error in source code ... here, it must be a literal
                        this.ReportParserError(result, SemanticErrors.UnrecognizedLiteral, token);
                        result.SetContents(elements, null);
                        return(result);
                    }
                    else
                    {
                        // ... add the child element to the array elements.
                        elements.Add(element);
                    }
                }
            }
        }
        protected ByteArrayLiteralNode ParseByteArrayLiteral(ILiteralNodeParent parent, SpecialCharacterToken arrayToken, SpecialCharacterToken leftBracket)
        {
            // PARSE: <array literal> ::= '#[' <number literal>* ']'

            List <SmallIntegerLiteralNode> elements = new List <SmallIntegerLiteralNode>();
            ByteArrayLiteralNode           result   = new ByteArrayLiteralNode(parent, arrayToken, leftBracket);

            // Process tokens inside the array ...
            while (true)
            {
                // ... get next token in the array ...
                Token token = this.GetNextTokenxx(Preference.NegativeSign);

                // Is this closing parenthesis?
                if (VseCompatibleParser.IsClosingByteArrayBracket(token))
                {
                    // Closing parenthesis ... done with the array, return litral array node.
                    result.SetContents(elements, (SpecialCharacterToken)token);
                    this.ResidueToken = null;
                    return(result);
                }

                if (token is EofToken)
                {
                    // Unfinished source code ... return
                    result.SetContents(elements, null);
                    this.ReportParserError(parent, "Missing literal byte array closing bracket.", token);
                    this.ResidueToken = token;
                    return(result);
                }

                // PARSE: <numeric liteal>
                if (token is SmallIntegerToken)
                {
                    elements.Add(new SmallIntegerLiteralNode(result, (SmallIntegerToken)token, null));
                }
                else if (token is NegativeSignToken)
                {
                    NegativeSignToken negativeSign = (NegativeSignToken)token;
                    token = this.GetNextTokenxx(Preference.NegativeSign);
                    if (token is SmallIntegerToken)
                    {
                        elements.Add(new SmallIntegerLiteralNode(result, (SmallIntegerToken)token, negativeSign));
                    }
                    else
                    {
                        this.ReportParserError(parent, "Unrecognized literal.", token);
                        this.ResidueToken = token;
                        result.SetContents(elements, null);
                        return(result);
                    }
                }
                else
                {
                    this.ReportParserError(parent, "Unrecognized literal.", token);
                    this.ResidueToken = token;
                    result.SetContents(elements, null);
                    return(result);
                }
            }
        }