Beispiel #1
0
        public static CALL parse(EXPRESSION reference, iSCOPE context)
        {
            CALL call = new CALL(reference);

            Token token;

            while (true)
            {
                EXPRESSION arg = EXPRESSION.parse(null, context);
                call.add(arg);
                token = get();
                if (token.code == TokenCode.Comma)
                {
                    forget(); continue;
                }
                break;
            }
            token = expect(TokenCode.RParen);
            call.setSpan(reference.span, token.span);

            return(call);
        }
Beispiel #2
0
        public static new EXPRESSION parse(Token first, iSCOPE context)
        {
            EXPRESSION result = PRIMARY.parse(first, context);

            if (result == null)
            {
                return(null);
            }

            Span begin = result.span;

            while (true)
            {
                Token token = get();
                switch (token.code)
                {
                case TokenCode.Dot:
                    forget();
                    IDENTIFIER identifier;
                    token = get();
                    if (token.code == TokenCode.Init)
                    {
                        forget();
                        // Initializer call in full form
                        identifier = new IDENTIFIER(INITIALIZER.initName);
                    }
                    else if (token.code == TokenCode.Identifier)
                    {
                        forget();
                        identifier = new IDENTIFIER(token);
                    }
                    else     // syntax error
                    {
                        identifier = new IDENTIFIER("ERROR");
                    }
                    result = new MEMBER(result, identifier);
                    result.setSpan(begin, token.span);
                    break;

                case TokenCode.LParen:
                    forget();
                    result = new CALL(result);
                    while (true)
                    {
                        token = get();
                        if (token.code == TokenCode.RParen)
                        {
                            forget(); break;
                        }
                        EXPRESSION actual = EXPRESSION.parse(null, context);
                        (result as CALL).add(actual);
                        token = get();
                        if (token.code == TokenCode.Comma)
                        {
                            forget(); continue;
                        }
                        token = expect(TokenCode.RParen);
                        break;
                    }
                    result.setSpan(begin, token.span);
                    break;

                default:
                    goto Out;
                }
            }
Out:
            return(result);
        }
Beispiel #3
0
        /// <summary>
        /// The function processes all kinds of statements including
        /// assignments, calls, and variable/constant declarations.
        /// </summary>
        /// <param name="context"></param>
        /// <returns>true, if any construct (a statement, or a simple declaration)
        /// was processed, and false otherwise.</returns>
        public static bool parse(iSCOPE context, TokenCode stop1, TokenCode stop2, TokenCode stop3)
        {
            Debug.Indent();
            Debug.WriteLine("Entering STATEMENT.parse");

            bool result = true;

            Token token = get();
            Token begin = token;

            if (token.code == stop1 && stop1 != TokenCode.ERROR)
            {
                goto Finish;
            }
            if (token.code == stop2 && stop2 != TokenCode.ERROR)
            {
                goto Finish;
            }
            if (token.code == stop3 && stop3 != TokenCode.ERROR)
            {
                goto Finish;
            }

            switch (token.code)
            {
            // case TokenCode.Pure: -- doesn't make any sense
            case TokenCode.Safe:
            case TokenCode.Routine:
                ROUTINE.parse(token, false, false, false, 0, context);
                break;

            case TokenCode.If:
                IF.parse(context);
                break;

            case TokenCode.While:
            case TokenCode.Loop:
                LOOP.parse(null, context);
                break;

            // Break
            //     : break [ Label ]
            //
            // Label
            //     : Identifier
            case TokenCode.Break:
                BREAK.parse(context);
                break;

            // Statement
            //     : ...
            //     | raise [ Expression ]
            case TokenCode.Raise:
                forget();
                RAISE.parse(token.span, context);
                break;

            // Statement
            //     : ...
            //     | check PredicatesList end
            //     | ...
            case TokenCode.Check:
                CHECK.parse(context);
                break;

            // Statement
            //     : ...
            //     | return [ Expression ]
            //     | ...
            case TokenCode.Return:
                forget();
                EXPRESSION expr = EXPRESSION.parse(null, context);    // can be null
                RETURN     ret  = new RETURN(expr);
                if (expr != null)
                {
                    expr.parent = ret;
                    ret.setSpan(begin.span, expr.span);
                }
                else
                {
                    ret.setSpan(begin);
                }

                context.add(ret);
                break;

            // Statement
            //     : ...
            //     | Try
            //     | ...
            //
            // Try
            //     : try { Statement } Catches [ Else ] end
            //
            // Catches
            //     : catch [ "(" [ Identifier ":" ] Type ")" ] { Statement }
            //
            // Else
            //     : else { Statement }
            case TokenCode.Try:
                TRY.parse(context);
                break;

            // Statement
            //     : ...
            //     | ? Identifier
            //     | ...
            //
            case TokenCode.Question:

                break;

            case TokenCode.Init:
                // Initializer call
                forget();
                Token start = token;

                DECLARATION init = Context.find(INITIALIZER.initName);
                EXPRESSION  initRef;
                if (init != null)
                {
                    initRef = new REFERENCE(init);
                }
                else
                {
                    initRef = new UNRESOLVED(context, new IDENTIFIER(INITIALIZER.initName));
                }

                CALL call = new CALL(initRef);
                token = expect(TokenCode.LParen);
                while (true)
                {
                    EXPRESSION argument = EXPRESSION.parse(null, context);
                    call.add(argument);
                    argument.parent = call;

                    token = get();
                    if (token.code == TokenCode.Comma)
                    {
                        forget(); continue;
                    }
                    break;
                }
                token = expect(TokenCode.RParen);
                call.setSpan(start.span, token.span);
                context.add(call);
                break;

            case TokenCode.Identifier:
            {
                // Several different cases:
                //   - a label in front of while/loop
                //   - a declaration
                //   - a statement

                forget();
                Token next = get();
                if (next.code == TokenCode.LParen)
                {
                    forget();
                    TokenCode codeAfter = saveTokensUntilRightParenth(next);
                    switch (codeAfter)
                    {
                    case TokenCode.Colon:
                    case TokenCode.Is:
                    // case TokenCode.Do:
                    case TokenCode.Arrow:
                        //This as a routine declaration!!
                        ROUTINE.parse(token, false, false, false, 0, context);
                        goto Weiter;
                    }
                }
                EXPRESSION attempt = EXPRESSION.parse(token, context);
                if (attempt is UNRESOLVED)
                {
                    // Might be a label or a declaration...
                    Token idd = new Token(attempt.span, TokenCode.Identifier,
                                          (attempt as UNRESOLVED).name.identifier,
                                          new Category(CategoryCode.identifier));
                    token = get();
                    switch (token.code)
                    {
                    case TokenCode.Is:
                    case TokenCode.Comma:
                        // This is definitely a declaration
                        forget();
                        VARIABLE.parse(false, false, false, false, idd, token, context);
                        goto Weiter;

                    case TokenCode.Colon:
                        forget();
                        Token token2 = get();
                        if (token2.code == TokenCode.While || token2.code == TokenCode.Loop)
                        {
                            // This is a real label! Don't 'forget()'.
                            LOOP.parse(idd, context);
                        }
                        else
                        {
                            // This is definitely a variable declaration.
                            // Don't forget()
                            VARIABLE.parse(false, false, false, false, idd, token, context);
                        }
                        goto Weiter;

                    default:
                        // Nothing to do; just going further
                        break;
                    }
                }
                // 'attempt' is something else: a call or the left part of an assignment
                token = get();
                if (token.code == TokenCode.Assign)
                {
                    forget();
                    EXPRESSION right = EXPRESSION.parse(null, context);
                    ASSIGNMENT res   = new ASSIGNMENT(attempt, right);
                    res.setSpan(attempt.span, right.span);
                    context.add(res);
                }
                else
                {
                    if (!(attempt is CALL))       // something's wrong
                    {
                        result = false;
                    }
                    context.add(attempt);
                }
Weiter:
                break;
            }

            case TokenCode.Const:
                // Something like
                //     const a is 5...
                // OR
                //     const is a, b, ... end
                forget(); token = get();
                if (token.code == TokenCode.Is)
                {
                    forget();
                    CONSTANT.parse(context);
                }
                else
                {
                    VARIABLE.parse(false, false, true, false, null, null, context);
                }
                break;

            default:
                // Something else, e.g., (a... or this...
                // Either a function call or an assignment.
                //
                //     this := ...
                //     (if cond then a else b).f ...
                //     ^

                EXPRESSION e = EXPRESSION.parse(null, context);
                if (e == null)
                {
                    // Either an error or just the end of statement sequence
                    result = false;
                    break;
                }
                token = get();
                if (token.code == TokenCode.Assign)
                {
                    forget();
                    EXPRESSION right      = EXPRESSION.parse(null, context);
                    ASSIGNMENT assignment = new ASSIGNMENT(e, right);
                    assignment.setSpan(e.span, right.span);
                    context.add(assignment);
                }
                else
                {
                    context.add(e);
                }
                break;
            }
Finish:
            Debug.WriteLine("Exiting STATEMENT.parse");
            Debug.Unindent();

            return(result);
        }