Ejemplo n.º 1
0
        /// <summary>
        /// Called when the item is a literal item.
        /// </summary>
        /// <param name="target">The object that was passed to IParseItem.Visit.</param>
        /// <returns>The passed target or a modification of it.</returns>
        /// <exception cref="System.ArgumentNullException">If target is null.</exception>
        public IParseItem Visit(LiteralItem target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            ILGenerator gen   = compiler.CurrentGenerator;
            object      Value = target.Value;

            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
            if (Value == null)
            {
                gen.Emit(OpCodes.Ldnull);
            }
            else if (Value is bool)
            {
                if ((bool)Value == false)
                {
                    gen.Emit(OpCodes.Ldc_I4_0);
                }
                else
                {
                    gen.Emit(OpCodes.Ldc_I4_1);
                }
                gen.Emit(OpCodes.Box, typeof(bool));
            }
            else if (Value is double)
            {
                gen.Emit(OpCodes.Ldc_R8, (double)Value);
                gen.Emit(OpCodes.Box, typeof(double));
            }
            else if (Value is string)
            {
                gen.Emit(OpCodes.Ldstr, Value as string);
            }
            else
            {
                throw new InvalidOperationException(Resources.InvalidLiteralType);
            }
            gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateValue)));

            return(target);
        }
Ejemplo n.º 2
0
        public void GenralParse()
        {
            PlainParser           target = new PlainParser();
            TextElementEnumerator input1 = StringInfo.GetTextElementEnumerator(
                @"local a = 12 
t = { [34]= function() print(i) end } 
function Some(a, ...) 
    a, b, c = ... 
    for i= 12, 23 do 
        print(i) 
    end 
end"
                );
            IParseItem actual;

            actual = target.Parse(new Tokenizer(input1, null), null, null);

            // check the main block
            BlockItem block = actual as BlockItem;

            Assert.IsInstanceOf <BlockItem>(actual);
            Assert.IsNotNull(block.Children);
            Assert.AreEqual(3, block.Children.Count, "Block.Children.Count");
            ValidateDebug(block.Debug, "Block", "local a = 12 t = { [ 34 ] = function ( ) print ( i ) end } function Some ( a , ... ) a , b , c = ... for i = 12 , 23 do print ( i ) end end", 1, 1, 8, 4);

            // check the return statement of the main block
            {
                ReturnItem ret = block.Return;
                Assert.IsInstanceOf <ReturnItem>(block.Return);
                ValidateDebug(ret.Debug, "Block.Return", null, 0, 0, 0, 0);
                Assert.IsNotNull(ret.Expressions);
                Assert.AreEqual(0, ret.Expressions.Count);
            }

            // local a = 12
            {
                AssignmentItem init = block.Children[0] as AssignmentItem;
                Assert.IsNotNull(init, "Block.Children[0]");
                Assert.AreEqual(true, init.Local);
                ValidateDebug(init.Debug, "Block.Children[0]", "local a = 12", 1, 1, 1, 13);

                // check the names
                {
                    Assert.IsNotNull(init.Names, "Block.Children[0].Names");
                    Assert.AreEqual(1, init.Names.Count, "Block.Children[0].Names.Count");

                    NameItem name = init.Names[0] as NameItem;
                    Assert.IsNotNull(name, "Block.Children[0].Names[0]");
                    Assert.AreEqual("a", name.Name, "Block.Children[0].Names[0].Name");
                    ValidateDebug(name.Debug, "Block.Children[0].Names[0]", "a", 1, 7, 1, 8);
                }

                // check the expressions
                {
                    Assert.IsNotNull(init.Expressions, "Block.Children[0].Expressions");
                    Assert.AreEqual(1, init.Expressions.Count, "Block.Children[0].Expressions.Count");

                    LiteralItem literal = init.Expressions[0] as LiteralItem;
                    Assert.IsNotNull(literal, "Block.Children[0].Expressions[0]");
                    Assert.AreEqual(12.0, literal.Value, "Block.Children[0].Expressions[0].Value");
                    ValidateDebug(literal.Debug, "Block.Children[0].Expressions[0]", "12", 1, 11, 1, 13);
                }
            }

            // t = { [34]= function() print(i) end }
            {
                AssignmentItem init = block.Children[1] as AssignmentItem;
                Assert.IsNotNull(init, "Block.Children[1]");
                Assert.AreEqual(false, init.Local);
                ValidateDebug(init.Debug, "Block.Children[1]", "t = { [ 34 ] = function ( ) print ( i ) end }", 2, 1, 2, 38);

                // check the names
                {
                    Assert.IsNotNull(init.Names, "Block.Children[1].Names");
                    Assert.AreEqual(1, init.Names.Count, "Block.Children[1].Names.Count");

                    NameItem name = init.Names[0] as NameItem;
                    Assert.IsNotNull(name, "Block.Children[1].Names[0]");
                    Assert.AreEqual("t", name.Name, "Block.Children[1].Names[0].Name");
                    ValidateDebug(name.Debug, "Block.Children[1].Names[0]", "t", 2, 1, 2, 2);
                }

                // check the expressions
                {
                    Assert.IsNotNull(init.Expressions, "Block.Children[1].Expressions");
                    Assert.AreEqual(1, init.Expressions.Count, "Block.Children[1].Expressions.Count");

                    TableItem table = init.Expressions[0] as TableItem;
                    Assert.IsNotNull(table, "Block.Children[1].Expressions[0]");
                    ValidateDebug(table.Debug, "Block.Children[1].Expressions[0]", "{ [ 34 ] = function ( ) print ( i ) end }", 2, 5, 2, 38);

                    Assert.IsNotNull(table.Fields, "Block.Children[1].Expressions[0].Fields");
                    Assert.AreEqual(1, table.Fields.Count, "Block.Children[1].Expressions[0].Fields.Count");

                    var field = table.Fields[0];
                    {
                        LiteralItem literal = field.Key as LiteralItem;
                        Assert.IsNotNull(literal, "Block.Children[1].Expressions[0].Fields[0].Item1");
                        Assert.AreEqual(34.0, literal.Value, "Block.Children[1].Expressions[0].Fields[0].Item1.Value");
                        ValidateDebug(literal.Debug, "Block.Children[1].Expressions[0].Fields[0].Item1", "34", 2, 8, 2, 10);
                    }
                    {
                        FuncDefItem func = field.Value as FuncDefItem;
                        Assert.IsNotNull(func, "Block.Children[1].Expressions[0].Fields[0].Item2");
                        Assert.IsNull(func.InstanceName, "Block.Children[1].Expressions[0].Fields[0].Item2.InstanceName");
                        Assert.IsNull(func.Prefix, "Block.Children[1].Expressions[0].Fields[0].Item2.Prefix");
                        Assert.AreEqual(false, func.Local, "Block.Children[1].Expressions[0].Fields[0].Item2.Local");
                        Assert.IsNull(func.FunctionInformation, "Block.Children[1].Expressions[0].Fields[0].Item2.FunctionInformation");
                        ValidateDebug(func.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2", "function ( ) print ( i ) end", 2, 13, 2, 36);

                        // validate the block
                        {
                            BlockItem funcBlock = func.Block;
                            Assert.IsNotNull(funcBlock, "Block.Children[1].Expressions[0].Fields[0].Item2.Block");
                            ValidateDebug(funcBlock.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block", "print ( i )", 2, 24, 2, 32);


                            // validate the return
                            {
                                ReturnItem ret = funcBlock.Return;
                                Assert.IsNotNull(ret, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return");
                                ValidateDebug(ret.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return", null, 0, 0, 0, 0);
                                Assert.IsNotNull(ret.Expressions, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return.Expressions");
                                Assert.AreEqual(0, ret.Expressions.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return.Expressions.Count");
                            }

                            // validate the statement
                            {
                                Assert.IsNotNull(funcBlock.Children, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children");
                                Assert.AreEqual(1, funcBlock.Children.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children.Count");

                                // print ( i )
                                {
                                    FuncCallItem call = funcBlock.Children[0] as FuncCallItem;
                                    Assert.IsNotNull(call, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0]");
                                    Assert.AreEqual(true, call.Statement, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Statement");
                                    Assert.IsNull(call.InstanceName, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].InstanceName");
                                    ValidateDebug(call.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0]", "print ( i )", 2, 24, 2, 32);

                                    // validate the prefix
                                    {
                                        NameItem name = call.Prefix as NameItem;
                                        Assert.IsNotNull(call.Prefix, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix");
                                        Assert.AreEqual("print", name.Name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix.Name");
                                        ValidateDebug(name.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix.Name", "print", 2, 24, 2, 29);
                                    }

                                    // validate the arguments
                                    {
                                        Assert.IsNotNull(call.Arguments, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments");
                                        Assert.AreEqual(1, call.Arguments.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments.Count");

                                        NameItem name = call.Arguments[0].Expression as NameItem;
                                        Assert.IsNotNull(name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0]");
                                        Assert.AreEqual("i", name.Name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0].Name");
                                        ValidateDebug(name.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0]", "i", 2, 30, 2, 31);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // function Some(a, ...)
            {
                FuncDefItem func = block.Children[2] as FuncDefItem;
                Assert.IsNotNull(func, "Block.Children[2]");
                Assert.AreEqual(false, func.Local, "Block.Children[2].Local");
                Assert.IsNull(func.InstanceName, "Block.Children[2].InstanceName");
                ValidateDebug(func.Debug, "Block.Children[2]", "function Some ( a , ... ) a , b , c = ... for i = 12 , 23 do print ( i ) end end", 3, 1, 8, 4);

                // validate the block
                {
                    BlockItem someBlock = func.Block;
                    ValidateDebug(someBlock.Debug, "Block.Children[2].Block", "a , b , c = ... for i = 12 , 23 do print ( i ) end", 4, 5, 7, 8);

                    // validate the return
                    {
                        ReturnItem ret = someBlock.Return;
                        Assert.IsNotNull(ret, "Block.Children[2].Block.Return");
                        ValidateDebug(ret.Debug, "Block.Children[2].Block.Return", null, 0, 0, 0, 0);
                        Assert.IsNotNull(ret.Expressions, "Block.Children[2].Block.Return.Expressions");
                        Assert.AreEqual(0, ret.Expressions.Count, "Block.Children[2].Block.Return.Expressions.Count");
                    }

                    // check the children
                    {
                        Assert.IsNotNull(someBlock.Children, "Block.Children[2].Block.Children");
                        Assert.AreEqual(2, someBlock.Children.Count, "Block.Children[2].Block.Children.Count");

                        // a , b , c = ...
                        {
                            AssignmentItem varInit = someBlock.Children[0] as AssignmentItem;
                            Assert.IsNotNull(varInit, "Block.Children[2].Block.Children[0]");
                            Assert.AreEqual(false, varInit.Local, "Block.Children[2].Block.Children[0].Local");
                            ValidateDebug(varInit.Debug, "Block.Children[2].Block.Children[0]", "a , b , c = ...", 4, 5, 4, 18);

                            // validate the names
                            {
                                Assert.IsNotNull(varInit.Names, "Block.Children[2].Block.Children[0].Names");
                                Assert.AreEqual(3, varInit.Names.Count, "Block.Children[2].Block.Children[0].Names.Count");

                                NameItem name = varInit.Names[0] as NameItem;
                                Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[0]");
                                Assert.AreEqual(name.Name, "a", "Block.Children[2].Block.Children[0].Names[0].Name");
                                ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[0]", "a", 4, 5, 4, 6);

                                name = varInit.Names[1] as NameItem;
                                Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[1]");
                                Assert.AreEqual(name.Name, "b", "Block.Children[2].Block.Children[0].Names[1].Name");
                                ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[1]", "b", 4, 8, 4, 9);

                                name = varInit.Names[2] as NameItem;
                                Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[2]");
                                Assert.AreEqual(name.Name, "c", "Block.Children[2].Block.Children[0].Names[2].Name");
                                ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[2]", "c", 4, 11, 4, 12);
                            }
                            // validate the expressions
                            {
                                Assert.IsNotNull(varInit.Expressions, "Block.Children[2].Block.Children[0].Expressions");
                                Assert.AreEqual(1, varInit.Expressions.Count, "Block.Children[2].Block.Children[0].Expressions.Count");

                                NameItem name = varInit.Expressions[0] as NameItem;
                                Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Expressions[0]");
                                Assert.AreEqual(name.Name, "...", "Block.Children[2].Block.Children[0].Expressions[0].Name");
                                ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Expressions[0]", "...", 4, 15, 4, 18);
                            }
                        }
                        // for i= 12, 23 do print ( i ) end
                        {
                            ForNumItem forLoop = someBlock.Children[1] as ForNumItem;
                            Assert.IsNotNull(forLoop, "Block.Children[2].Block.Children[1]");
                            ValidateDebug(forLoop.Debug, "Block.Children[2].Block.Children[1]", "for i = 12 , 23 do print ( i ) end", 5, 5, 7, 8);

                            // validate the name
                            {
                                NameItem name = forLoop.Name;
                                Assert.IsNotNull(name, "Block.Children[2].Block.Children[1].Name");
                                ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Name", "i", 5, 9, 5, 10);
                                Assert.AreEqual(name.Name, "i", "Block.Children[2].Block.Children[1].Name.Name");
                            }

                            // validate the start
                            {
                                LiteralItem lit = forLoop.Start as LiteralItem;
                                Assert.IsNotNull(lit, "Block.Children[2].Block.Children[1].Start");
                                Assert.AreEqual(12.0, lit.Value, "Block.Children[2].Block.Children[1].Start.Value");
                                ValidateDebug(lit.Debug, "Block.Children[2].Block.Children[1].Start", "12", 5, 12, 5, 14);
                            }

                            // validate the limit
                            {
                                LiteralItem lit = forLoop.Limit as LiteralItem;
                                Assert.IsNotNull(lit, "Block.Children[2].Block.Children[1].Limit");
                                Assert.AreEqual(23.0, lit.Value, "Block.Children[2].Block.Children[1].Limit.Value");
                                ValidateDebug(lit.Debug, "Block.Children[2].Block.Children[1].Limit", "23", 5, 16, 5, 18);
                            }

                            // validate the step
                            {
                                Assert.IsNull(forLoop.Step, "Block.Children[2].Block.Children[1].Step");
                            }

                            // validate the block
                            {
                                BlockItem forBlock = forLoop.Block;
                                ValidateDebug(forBlock.Debug, "Block.Children[2].Block.Children[1].Block", "print ( i )", 6, 9, 6, 17);
                                Assert.IsNull(forBlock.Return, "Block.Children[2].Block.Children[1].Block.Return");

                                // validate the statement
                                {
                                    Assert.IsNotNull(forBlock.Children, "Block.Children[2].Block.Children[1].Block.Children");
                                    Assert.AreEqual(1, forBlock.Children.Count, "Block.Children[2].Block.Children[1].Block.Children.Count");

                                    // print ( i )
                                    {
                                        FuncCallItem call = forBlock.Children[0] as FuncCallItem;
                                        Assert.IsNotNull(call, "Block.Children[2].Block.Children[1].Block.Children[0]");
                                        Assert.AreEqual(true, call.Statement, "Block.Children[2].Block.Children[1].Block.Children[0].Statement");
                                        Assert.IsNull(call.InstanceName, "Block.Children[2].Block.Children[1].Block.Children[0].InstanceName");
                                        ValidateDebug(call.Debug, "Block.Children[2].Block.Children[1].Block.Children[0]", "print ( i )", 6, 9, 6, 17);

                                        // validate the prefix
                                        {
                                            NameItem name = call.Prefix as NameItem;
                                            Assert.IsNotNull(call.Prefix, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix");
                                            Assert.AreEqual("print", name.Name, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix.Name");
                                            ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix.Name", "print", 6, 9, 6, 14);
                                        }

                                        // validate the arguments
                                        {
                                            Assert.IsNotNull(call.Arguments, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments");
                                            Assert.AreEqual(1, call.Arguments.Count, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments.Count");

                                            NameItem name = call.Arguments[0].Expression as NameItem;
                                            Assert.IsNotNull(name, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0]");
                                            Assert.AreEqual("i", name.Name, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0].Name");
                                            ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0]", "i", 6, 15, 6, 16);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Reads a function from the input.  Input must be on the word 'function'.  If canName is true,
        /// it will give the function the read name; otherwise it will give it a null name.
        /// </summary>
        /// <param name="input">Where to read input from.</param>
        /// <param name="canName">True if the function can have a name, otherwise false.</param>
        /// <param name="local">True if this function is a local definition, otherwise false.</param>
        /// <returns>The function definition that was read.</returns>
        protected virtual FuncDefItem _readFunctionHelper(Lexer input, bool canName, bool local)
        {
            Token debug = input.Expect(TokenType.Function);

            IParseVariable name     = null;
            string         instName = null;

            if (input.PeekType(TokenType.Identifier))
            {
                Token temp = input.Expect(TokenType.Identifier);
                name = new NameItem(temp.Value)
                {
                    Debug = temp
                };
                while (input.ReadIfType(TokenType.Indexer))
                {
                    temp = input.Expect(TokenType.Identifier);
                    var literal = new LiteralItem(temp.Value)
                    {
                        Debug = temp
                    };
                    name = new IndexerItem(name, literal)
                    {
                        Debug = name.Debug
                    };
                }

                if (input.ReadIfType(TokenType.Colon))
                {
                    instName = input.Expect(TokenType.Identifier).Value;
                }
            }
            if (name != null && !canName)
            {
                throw new SyntaxException(Resources.FunctionCantHaveName, input.Name, debug);
            }
            if (name == null && canName)
            {
                throw new SyntaxException("Function statements must provide name", input.Name, debug);
            }

            var args = new List <NameItem>();

            input.Expect(TokenType.BeginParen);
            if (!input.PeekType(TokenType.EndParen))
            {
                do
                {
                    Token temp = input.PeekType(TokenType.Elipsis) ?
                                 input.Expect(TokenType.Elipsis) :
                                 input.Expect(TokenType.Identifier);
                    args.Add(new NameItem(temp.Value)
                    {
                        Debug = temp
                    });
                    if (temp.Value == "...")
                    {
                        break;
                    }
                } while (input.ReadIfType(TokenType.Comma));
            }
            input.Expect(TokenType.EndParen);
            BlockItem chunk = _readBlock(input);

            input.Expect(TokenType.End);
            chunk.Return ??= new ReturnItem();

            return(new FuncDefItem(args.ToArray(), chunk)
            {
                Debug = debug,
                InstanceName = instName,
                Prefix = name,
                Local = local,
            });
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Reads an expression from the input.
        /// </summary>
        /// <param name="input">Where to read input from.</param>
        /// <param name="precedence">The precedence of the previous expression or -1 if a root.</param>
        /// <returns>The expression that was read.</returns>
        protected virtual IParseExp _readExp(Lexer input, out bool isParentheses, int precedence = -1)
        {
            Token     debug = input.Peek();
            IParseExp ret;
            var       unOpType = _getUnaryOperationType(input.Peek().Type);

            isParentheses = false;
            if (unOpType != UnaryOperationType.Unknown)
            {
                input.Read();
                int unaryPrec = 11;
                if (unaryPrec > precedence && precedence >= 0)
                {
                    unaryPrec = precedence;
                }
                ret = new UnOpItem(_readExp(input, out _, unaryPrec), unOpType)
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.Nil))
            {
                ret = new LiteralItem(null)
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.False))
            {
                ret = new LiteralItem(false)
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.True))
            {
                ret = new LiteralItem(true)
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.NumberLiteral))
            {
                ret = new LiteralItem(Helpers.ParseNumber(debug.Value))
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.StringLiteral))
            {
                ret = new LiteralItem(debug.Value)
                {
                    Debug = debug
                };
            }
            else if (input.ReadIfType(TokenType.Elipsis))
            {
                ret = new NameItem("...")
                {
                    Debug = debug
                };
            }
            else if (input.PeekType(TokenType.BeginTable))
            {
                ret = _readTable(input);
            }
            else if (input.PeekType(TokenType.Function))
            {
                ret = _readFunctionHelper(input, false, false);
            }
            else
            {
                ret = _readPrefixExp(input, out isParentheses);
            }

            while (true)
            {
                BinaryOperationType binOpType = _getBinaryOperationType(input.Peek().Type);
                int newPrecedence             = _getPrecedence(binOpType);
                if (binOpType == BinaryOperationType.Unknown ||
                    (newPrecedence < precedence && precedence >= 0))
                {
                    break;
                }
                input.Read();

                // For left-associative operations, use a lower precedence so the nested call doesn't read
                // more than it should.  a+b+c should be (a+b)+c, so we need the first add to be its own
                // item and then have that should be the lhs of another add.  Note this only works if
                // operations of the same precedence have the same associativity.
                int       extra = _isRightAssociative(binOpType) ? 0 : 1;
                IParseExp other = _readExp(input, out _, newPrecedence + extra);
                ret = new BinOpItem(ret, binOpType, other)
                {
                    Debug = debug
                };
                isParentheses = false;
            }
            return(ret);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Reads a prefix-expression from the input.
        /// </summary>
        /// <param name="input">The input to read from.</param>
        /// <returns>The parsed expression.</returns>
        protected virtual IParseExp _readPrefixExp(Lexer input, out bool isParentheses)
        {
            Token     debug = input.Peek();
            IParseExp ret;

            if (input.ReadIfType(TokenType.BeginParen))
            {
                isParentheses = true;
                ret           = _readExp(input, out _);
                input.Expect(TokenType.EndParen);
            }
            else
            {
                isParentheses = false;
                Token name = input.Expect(TokenType.Identifier);
                ret = new NameItem(name.Value)
                {
                    Debug = name
                };
            }

            while (true)
            {
                if (input.ReadIfType(TokenType.BeginBracket))
                {
                    isParentheses = false;
                    IParseExp temp = _readExp(input, out _);
                    ret = new IndexerItem(ret, temp)
                    {
                        Debug = debug
                    };
                    input.Expect(TokenType.EndBracket);
                }
                else if (input.ReadIfType(TokenType.Indexer))
                {
                    isParentheses = false;
                    Token token = input.Expect(TokenType.Identifier);
                    var   name  = new LiteralItem(token.Value)
                    {
                        Debug = token
                    };
                    ret = new IndexerItem(ret, name)
                    {
                        Debug = debug
                    };
                }
                else
                {
                    string instName = null;
                    int    overload = -1;
                    if (input.ReadIfType(TokenType.Colon))
                    {
                        instName = input.Expect(TokenType.Identifier).Value;
                        int idx = instName.IndexOf('`');
                        if (idx >= 0)
                        {
                            if (!int.TryParse(instName.Substring(idx + 1), out overload))
                            {
                                throw input.SyntaxError(Resources.OnlyNumbersInOverload);
                            }
                            instName = instName.Substring(0, idx);
                        }
                    }
                    else if (ret is NameItem name)
                    {
                        int idx = name.Name.IndexOf('`');
                        if (idx >= 0)
                        {
                            if (!int.TryParse(name.Name.Substring(idx + 1), out overload))
                            {
                                throw input.SyntaxError(Resources.OnlyNumbersInOverload);
                            }
                            name.Name = name.Name.Substring(0, idx);
                        }
                    }

                    bool isLastSingle = false;
                    var  args         = new List <FuncCallItem.ArgumentInfo>();
                    if (input.PeekType(TokenType.BeginTable))
                    {
                        args.Add(new FuncCallItem.ArgumentInfo(_readTable(input), false));
                    }
                    else if (input.PeekType(TokenType.StringLiteral))
                    {
                        Token token = input.Expect(TokenType.StringLiteral);
                        args.Add(new FuncCallItem.ArgumentInfo(new LiteralItem(token.Value)
                        {
                            Debug = token
                        },
                                                               false));
                    }
                    else if (input.ReadIfType(TokenType.BeginParen))
                    {
                        if (!input.PeekType(TokenType.EndParen))
                        {
                            do
                            {
                                bool isRef      = input.ReadIfType(TokenType.Ref);
                                bool isRefParen = false;
                                if (isRef)
                                {
                                    isRefParen = input.ReadIfType(TokenType.BeginParen);
                                }
                                else
                                {
                                    isRef = input.ReadIfType(TokenType.RefSymbol);
                                }

                                args.Add(new FuncCallItem.ArgumentInfo(_readExp(input, out isLastSingle), isRef));
                                if (isRefParen)
                                {
                                    input.Expect(TokenType.EndParen);
                                }
                            } while (input.ReadIfType(TokenType.Comma));
                        }
                        input.Expect(TokenType.EndParen);
                    }
                    else
                    {
                        break;
                    }
                    isParentheses = false;
                    ret           = new FuncCallItem(ret, args.ToArray())
                    {
                        Debug           = debug,
                        InstanceName    = instName,
                        Overload        = overload,
                        IsLastArgSingle = isLastSingle,
                    };
                }
            }
            return(ret);
        }
Ejemplo n.º 6
0
 public IParseItem Visit(LiteralItem target)
 {
     // Do nothing.
     return(target);
 }