Пример #1
0
            private static object ReadMethodCall(SimpleParser parser, object prevData, string name)
            {
                using (var la = parser.LookAround())
                {
                    parser.SkipSpaces();
                    if (parser.ReadChar('('))
                    {
                        var prevType = prevData as Type;

                        if (prevType != null)
                        {
                            var isMethodGroup = prevType.GetMethods(BindingFlags.Static | BindingFlags.Public).Any(m => m.Name == name);
                            if (isMethodGroup)
                            {
                                var paramValues = parser.ReadList <ValueBuilder, INode>(ReadListSeparator);
                                if (paramValues.Count == 1 && paramValues[0] == null)
                                {
                                    paramValues.Clear();
                                }

                                parser.SkipSpaces();
                                if (parser.ReadChar(')'))
                                {
                                    la.Success();
                                    return(new Call {
                                        Type = prevType, Element = null, Name = name, Parameters = paramValues
                                    });
                                }
                            }
                        }
                        else
                        {
                            var prevExecutor = (INode)prevData;
                            var type         = prevData == null ? parser.GlobalType : prevExecutor.Compile(parser.GlobalType);

                            var isMethodGroup = type.GetMethods(BindingFlags.Instance | BindingFlags.Public).Any(m => m.Name == name);
                            if (isMethodGroup)
                            {
                                var paramValues = parser.ReadList <ValueBuilder, INode>(ReadListSeparator);
                                if (paramValues.Count == 1 && paramValues[0] == null)
                                {
                                    paramValues.Clear();
                                }

                                parser.SkipSpaces();
                                if (parser.ReadChar(')'))
                                {
                                    la.Success();
                                    return(new Call {
                                        Element = prevExecutor, Name = name, Parameters = paramValues
                                    });
                                }
                            }
                        }
                    }

                    return(null);
                }
            }
Пример #2
0
            /// <summary>
            /// Reads the code trying to extract the AST from it.
            /// </summary>
            /// <param name="parser">The parser object used to read the code.</param>
            /// <param name="prevData">Previously parsed result. This is used to chain results together.</param>
            /// <returns>Returns an object that results from parsing the code.</returns>
            public override object Read(SimpleParser parser, object prevData)
            {
                var prevExecutor = prevData as INode;

                parser.SkipSpaces();

                if (prevData == null)
                {
                    var name = this.ReadName(parser);

                    // this is a direct method call in the root
                    var call = ReadMethodCall(parser, null, name);
                    if (call != null)
                    {
                        return(call);
                    }

                    // this is a global property
                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        var typeReference = parser.StaticTypes.SingleOrDefault(t => t.Name == name);
                        if (typeReference != null)
                        {
                            return(typeReference);
                        }

                        return(new PropertyGet {
                            Name = name, Element = null
                        });
                    }

                    // this is an array construct
                    if (parser.ReadChar('{'))
                    {
                        var values = parser.ReadList <ValueBuilder, INode>(ReadListSeparator);
                        if (values.Count > 0)
                        {
                            parser.SkipSpaces();
                            if (!parser.ReadChar('}'))
                            {
                                return(new Exception("Unterminated array construct."));
                            }

                            return(new ArrayConstruct {
                                Values = values
                            });
                        }
                    }

                    // this is a precedence operator
                    if (parser.ReadChar('('))
                    {
                        var value = parser.Read <ValueBuilder, INode>();
                        if (value == null)
                        {
                            return(new Exception("Syntax error."));
                        }

                        parser.SkipSpaces();
                        if (!parser.ReadChar(')'))
                        {
                            return(new Exception("Unterminated precedence construct."));
                        }

                        return(value);
                    }

                    // this is a number literal
                    var number = parser.ReadWhileCharOrEof(char.IsNumber);
                    if (number.Length > 0)
                    {
                        return new NumberLiteral {
                                   Data = number
                        }
                    }
                    ;

                    // this is a string literal
                    if (parser.ReadChar('"'))
                    {
                        var strBuilder = new StringBuilder();

                        while (true)
                        {
                            strBuilder.Append(parser.ReadWhileCharOrEof(ch => ch != '\\' && ch != '"'));

                            if (parser.Eof)
                            {
                                return(new InvalidOperationException("String literal not terminated."));
                            }

                            if (parser.ReadChar('\\'))
                            {
                                if (parser.ReadChar('0'))
                                {
                                    strBuilder.Append('\0');
                                }
                                else if (parser.ReadChar('n'))
                                {
                                    strBuilder.Append('\n');
                                }
                                else if (parser.ReadChar('r'))
                                {
                                    strBuilder.Append('\r');
                                }
                                else if (parser.ReadChar('\\'))
                                {
                                    strBuilder.Append('\\');
                                }
                                else if (parser.ReadChar('"'))
                                {
                                    strBuilder.Append('"');
                                }
                                else
                                {
                                    return(new InvalidOperationException("Escape sequence not recognized."));
                                }
                            }

                            if (parser.ReadChar('"'))
                            {
                                break;
                            }
                        }

                        return(new StringLiteral {
                            Data = strBuilder.ToString()
                        });
                    }
                }
                else
                {
                    if (parser.ReadChar('.'))
                    {
                        var name = this.ReadName(parser);

                        // this is a direct method call in the previous element
                        var call = ReadMethodCall(parser, prevData, name);
                        if (call != null)
                        {
                            return(call);
                        }

                        if (!string.IsNullOrWhiteSpace(name))
                        {
                            return new PropertyGet {
                                       Name = name, Element = prevExecutor
                            }
                        }
                        ;
                    }

                    // indexer property
                    if (parser.ReadChar('['))
                    {
                        var indexValues = parser.ReadList <ValueBuilder, INode>(ReadListSeparator);

                        if (indexValues.Count == 0)
                        {
                            return(new Exception("Index is missing."));
                        }

                        parser.SkipSpaces();
                        if (!parser.ReadChar(']'))
                        {
                            return(new Exception("Unterminated indexer."));
                        }

                        return(new IndexerGet {
                            Element = prevExecutor, Indexes = indexValues
                        });
                    }

                    // this only happens when calling a delegate
                    // direct method calls never fall here
                    if (parser.ReadChar('('))
                    {
                        var paramValues = parser.ReadList <ValueBuilder, INode>(ReadListSeparator);

                        parser.SkipSpaces();
                        if (parser.ReadChar(')'))
                        {
                            return new Call {
                                       Element = prevExecutor, Name = "Invoke", Parameters = paramValues
                            }
                        }
                        ;
                    }

                    if (parser.ReadChar('?'))
                    {
                        var trueValue = parser.Read <ValueBuilder, INode>();
                        parser.SkipSpaces();
                        if (!parser.ReadChar(':'))
                        {
                            throw new Exception("Missing ':' for ternary operator a?b:c.");
                        }
                        parser.SkipSpaces();
                        var falseValue = parser.Read <ValueBuilder, INode>();

                        return(new TernaryInlineIf {
                            Condition = prevExecutor, TrueValue = trueValue, FalseValue = falseValue
                        });
                    }

                    var binOp = parser.ReadAnyStringAlternative("==", "!=", ">", "<", ">=", "<=", "&&", "||");
                    if (binOp != null)
                    {
                        var valueB = parser.Read <ValueBuilder, INode>();

                        return(new BinaryBoolOps {
                            ValueA = prevExecutor, ValueB = valueB, Operator = binOp
                        });
                    }
                }

                return(null);
            }