Exemple #1
0
        public Type Parse(ParserContext context)
        {
            // Capture current type token.
            Token token = context.Stream.Current;

            // Ensure current token is a type.
            if (!TokenIdentifier.IsType(token, context))
            {
                throw new Exception($"Expected a type but got '{token.Type}'");
            }

            // Skip and capture the next token.
            Token nextToken = context.Stream.Next();

            // Create the array length (and flag), defaulting to null.
            uint?arrayLength = null;

            // Determine if type is an array.
            if (nextToken.Type == TokenType.SymbolBracketL)
            {
                // Skip bracket start token.
                context.Stream.Skip();

                // TODO: Must ensure array length is integer somehow.
                // TODO: Invoke expression parser to capture array length.
                // TODO: arrayLength.Value = new ExprParser().Parse(context);

                // TODO: BEGIN temporary solution.

                // Ensure current token is an integer.
                context.Stream.EnsureCurrent(TokenType.LiteralInteger);

                // Capture the current integer token.
                Token integerToken = context.Stream.Current;

                // Assign the token value as the array length.
                arrayLength = uint.Parse(integerToken.Value);

                // Skip over the captured integer token.
                context.Stream.Skip();

                // TODO: END temporary solution.

                // Ensure the current token is a closing bracket.
                context.Stream.EnsureCurrent(TokenType.SymbolBracketR);

                // Skip bracket end token.
                context.Stream.Skip();
            }

            // Update the next token buffer.
            nextToken = context.Stream.Get();

            // Create the pointer flag.
            bool isPointer = false;

            // Determine if pointer sequence exists.
            if (nextToken.Type == TokenType.OperatorMultiplication)
            {
                // Raise the pointer flag.
                isPointer = true;

                // Skip the pointer token.
                context.Stream.Skip();
            }

            // Create the type.
            return(new Type(context.SymbolTable, token, isPointer, arrayLength));
        }
Exemple #2
0
        public Block Parse(ParserContext context)
        {
            // Capture current token. Either block start or arrow for anonymous functions.
            Token begin = context.Stream.Current;

            // Skip begin token.
            context.Stream.Skip();

            // Create the block.
            Block block = new Block();

            // Set the block as active in the symbol table.
            context.SymbolTable.activeBlock = block;

            // Mark the block as default.
            if (begin.Type == TokenType.SymbolBlockL)
            {
                block.Type = BlockType.Default;
            }
            // Mark the block as short.
            else if (begin.Type == TokenType.SymbolArrow)
            {
                block.Type = BlockType.Short;
            }
            // Otherwise, the block type could not be identified.
            else
            {
                throw new Exception("Unexpected block type");
            }

            // Begin the iteration.
            context.Stream.NextUntil(TokenType.SymbolBlockR, (Token token) =>
            {
                // Returning a value.
                if (token.Type == TokenType.KeywordReturn)
                {
                    // Invoke the return parser. It's okay if it returns null, as it will be emitted as void.
                    Expr returnExpr = new FunctionReturnParser().Parse(context);

                    // Assign the return expression to the block.
                    block.ReturnExpr = returnExpr;

                    // Return immediatly, signal to update the token buffer to the current token.
                    return(true);
                }

                // Token must be a statement.
                Expr statement = new StatementParser().Parse(context);

                // Ensure statement was successfully parsed.
                if (statement == null)
                {
                    throw new Exception("Unexpected statement to be null");
                }

                // Append the parsed statement to the block's expression list.
                block.Expressions.Add(statement);

                // Ensure current token is a semi-colon, if previous statement did not parse a block.
                if (statement.ExprType != ExprType.If)
                {
                    // Ensure semi-colon token.
                    context.Stream.EnsureCurrent(SyntaxAnalysis.TokenType.SymbolSemiColon);

                    // Skip over the semi-colon.
                    context.Stream.Skip();
                }

                // Signal to update the token buffer with the current token.
                return(true);
            });

            // Skip onto default block end or short block end.
            context.Stream.Skip();

            // Return the resulting block.
            return(block);
        }
Exemple #3
0
        public FormalArgs Parse(ParserContext context)
        {
            // Ensure position.
            context.Stream.EnsureCurrent(TokenType.SymbolParenthesesL);

            // Skip parentheses start.
            context.Stream.Skip();

            // Create the formal args entity.
            FormalArgs args = new FormalArgs();

            // Create the loop buffer token.
            Token buffer = context.Stream.Current;

            // Loop until parentheses end.
            while (buffer.Type != TokenType.SymbolParenthesesR)
            {
                // Continuous arguments.
                if (!args.Continuous && buffer.Type == TokenType.SymbolContinuous)
                {
                    // Set the continuous flag.
                    args.Continuous = true;

                    // Advance stream immediatly.
                    buffer = context.Stream.Next(TokenType.SymbolParenthesesR);

                    // Continue loop.
                    continue;
                }
                // Continuous arguments must be final.
                else if (args.Continuous)
                {
                    throw new Exception("Unexpected token after continuous arguments");
                }

                // Invoke the arg parser.
                FormalArg arg = new FormalArgParser().Parse(context);

                // Update the buffer.
                buffer = context.Stream.Current;

                // Ensure next token is valid.
                if (buffer.Type != TokenType.SymbolComma && buffer.Type != TokenType.SymbolParenthesesR)
                {
                    throw new Exception($"Unexpected token of type '{buffer.Type}'; Expected comma or parentheses end in argument list");
                }
                // Skip the comma token.
                else if (buffer.Type == TokenType.SymbolComma)
                {
                    context.Stream.Skip();

                    // Make sure to update the buffer after skipping the comma token.
                    buffer = context.Stream.Current;
                }

                // Append the parsed argument.
                args.Values.Add(arg);
            }

            // Ensure current token is parentheses end.
            context.Stream.EnsureCurrent(TokenType.SymbolParenthesesR);

            // Skip parentheses end token.
            context.Stream.Skip();

            // Finish process.
            return(args);
        }