Beispiel #1
0
        /// <summary>
        /// Parse Script
        /// </summary>
        /// <exception cref="ScriptParsingException"></exception>
        public Script(
            IEnumerator <Token> scriptTokens,
            params FunctionSignature[] expectedFunctions)
        {
            ScriptCompilationContext compilationContext = new ScriptCompilationContext();

            while (!(scriptTokens.Current is EOFToken))
            {
                ParseNextGlobal(scriptTokens, compilationContext);
            }

            foreach (FunctionSignature data in expectedFunctions)
            {
                if (!scriptFunctions.ContainsKey(data.identifierToken.identifier))
                {
                    throw new ScriptParsingException(
                              source: scriptTokens.Current ?? new EOFToken(0, 0),
                              message: $"Expected Function not found: {data}");
                }

                if (!data.Matches(scriptFunctions[data.identifierToken.identifier].functionSignature))
                {
                    throw new ScriptParsingException(
                              source: scriptFunctions[data.identifierToken.identifier].functionSignature.identifierToken,
                              message: $"Expected Function: {data}  Found Function: {scriptFunctions[data.identifierToken.identifier].functionSignature}");
                }
            }

            foreach (ScriptFunction scriptFunction in scriptFunctions.Values)
            {
                scriptFunction.ParseFunctions(compilationContext);
            }
        }
Beispiel #2
0
        public void ParseNextGlobal(
            IEnumerator <Token> scriptTokens,
            ScriptCompilationContext context)
        {
            switch (scriptTokens.Current)
            {
            case KeywordToken kwToken:
                //Valid operations:
                //  Global declaration
                //  Extern declaration
                //  Member declaration
                //  Class declaration
                switch (kwToken.keyword)
                {
                case Keyword.Global:
                case Keyword.Extern:
                    //Parse Global Declaration
                {
                    scriptTokens.CautiousAdvance();

                    Type valueType = scriptTokens.ReadType();

                    IdentifierToken identToken            = scriptTokens.GetTokenAndAdvance <IdentifierToken>();
                    IValueGetter    initializerExpression = null;

                    if (scriptTokens.TestAndConditionallySkip(Operator.Assignment))
                    {
                        initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context);
                    }

                    scriptTokens.AssertAndSkip(Separator.Semicolon, false);

                    scriptDeclarations.Add(
                        new GlobalDeclaration(
                            identifierToken: identToken,
                            valueType: valueType,
                            isExtern: kwToken.keyword == Keyword.Extern,
                            initializer: initializerExpression,
                            context: context));
                }
                    return;

                case Keyword.Const:
                {
                    scriptTokens.CautiousAdvance();

                    Type valueType = scriptTokens.ReadType();

                    IdentifierToken identToken = scriptTokens.GetTokenAndAdvance <IdentifierToken>();
                    scriptTokens.AssertAndSkip(Operator.Assignment);
                    IValueGetter initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context);

                    scriptTokens.AssertAndSkip(Separator.Semicolon, false);

                    if (!(initializerExpression is LiteralToken litToken))
                    {
                        throw new ScriptParsingException(
                                  source: kwToken,
                                  message: $"The value of Const declarations must be constant");
                    }

                    object value = litToken.GetAs <object>();

                    if (!valueType.IsAssignableFrom(litToken.GetValueType()))
                    {
                        value = Convert.ChangeType(value, valueType);
                    }

                    context.DeclareConstant(
                        identifierToken: identToken,
                        type: valueType,
                        value: value);
                }
                    return;

                case Keyword.Void:
                case Keyword.Bool:
                case Keyword.Double:
                case Keyword.Integer:
                case Keyword.String:
                case Keyword.List:
                case Keyword.Queue:
                case Keyword.Stack:
                case Keyword.DepletableBag:
                case Keyword.DepletableList:
                case Keyword.RingBuffer:
                case Keyword.Dictionary:
                case Keyword.HashSet:
                case Keyword.Random:
                case Keyword.DataFile:
                    //Parse Function or Member Declaration
                {
                    Type            valueType  = scriptTokens.ReadType();
                    IdentifierToken identToken = scriptTokens.GetTokenAndAdvance <IdentifierToken>();

                    if (scriptTokens.TestWithoutSkipping(Separator.OpenParen))
                    {
                        VariableData[] arguments = ParseArgumentsDeclaration(scriptTokens);

                        if (scriptFunctions.ContainsKey(identToken.identifier))
                        {
                            throw new ScriptParsingException(
                                      source: identToken,
                                      message: $"Two declarations of function {identToken.identifier} found.");
                        }

                        scriptFunctions.Add(identToken.identifier,
                                            new ScriptFunction(
                                                functionTokens: scriptTokens,
                                                functionSignature: new FunctionSignature(
                                                    identifierToken: identToken,
                                                    returnType: valueType,
                                                    arguments: arguments),
                                                context: context));
                    }
                    else
                    {
                        //Member declaration
                        if (kwToken.keyword == Keyword.Void)
                        {
                            throw new ScriptParsingException(
                                      source: kwToken,
                                      message: $"Cannot declare a member of type Void");
                        }

                        IValueGetter initializerExpression = null;
                        if (scriptTokens.TestAndConditionallySkip(Operator.Assignment))
                        {
                            initializerExpression = Expression.ParseNextGetterExpression(scriptTokens, context);
                        }

                        scriptTokens.AssertAndSkip(Separator.Semicolon, false);

                        scriptDeclarations.Add(
                            new MemberDeclaration(
                                identifierToken: identToken,
                                valueType: valueType,
                                initializer: initializerExpression,
                                context: context));
                    }
                }
                    return;

                default:
                    throw new ScriptParsingException(
                              source: kwToken,
                              message: $"Token not valid for global context: {kwToken}.");
                }

            default:
                throw new ScriptParsingException(
                          source: scriptTokens.Current,
                          message: $"Token not valid for global context: {scriptTokens.Current}.");
            }
        }