Beispiel #1
0
        public IEnumerator <Parselet> Parse()
        {
            if (!parseletNames.Any())
            {
                throw new RantInternalException($"{GetType().Name}.Parse(): Parselet name stack is empty.");
            }

            if (!tokens.Any())
            {
                throw new RantInternalException($"{GetType().Name}.Parse(): Token stack is empty.");
            }

            if (!outputDelegates.Any())
            {
                throw new RantInternalException($"{GetType().Name}.Parse(): Output delegate stack is empty.");
            }

            var name  = parseletNames.Pop();
            var token = tokens.Pop();

            TokenParserDelegate tokenParser = null;

            if (!tokenParserMethods.TryGetValue(name, out tokenParser))
            {
                if (defaultParserMethod == null)
                {
                    throw new RantInternalException($"{GetType().Name}.Parse(): No valid implementation exists for R.{token.ID}.");
                }

                tokenParser = defaultParserMethod;
            }

            foreach (var parselet in tokenParser(token))
            {
                yield return(parselet);
            }

            outputDelegates.Pop();
        }
Beispiel #2
0
        protected Parselet()
        {
            tokenParserMethods = new Dictionary <string, TokenParserDelegate>();

            parseletNames   = new Stack <string>();
            tokens          = new Stack <Token <R> >();
            outputDelegates = new Stack <Action <RantAction> >();

            // it doesn't matter if the methods are private, we can still call them because reflection
#if UNITY
            var methods =
                from method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                let attrib = method.GetCustomAttributes(typeof(TokenParserAttribute), true).Cast <TokenParserAttribute>().FirstOrDefault()
                             let defaultAttrib = method.GetCustomAttributes(typeof(DefaultParserAttribute), true).Cast <DefaultParserAttribute>().FirstOrDefault()
                                                 where attrib != null || defaultAttrib != null
                                                 select new { Method = method, Attrib = attrib, IsDefault = defaultAttrib != null };
#else
            var methods =
                from method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                let attrib = method.GetCustomAttribute <TokenParserAttribute>()
                             let defaultAttrib = method.GetCustomAttribute <DefaultParserAttribute>()
                                                 where attrib != null || defaultAttrib != null
                                                 select new { Method = method, Attrib = attrib, IsDefault = defaultAttrib != null };
#endif


            if (!methods.Any())
            {
                throw new RantInternalException($"{GetType().Name}.ctor: No parselet implementations found.");
            }

            foreach (var method in methods)
            {
                if (method.Method.IsStatic)
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' musn't be static.");
                }

                if (method.Method.IsGenericMethod)
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' musn't be generic:.");
                }

                if (method.Method.GetParameters().Length != 1)
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: Invalid amount of parameters for parselet method '{method.Method.Name}'.");
                }

                if (method.Method.GetParameters().First().ParameterType != typeof(Token <R>))
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: Wrong parameter type for parselet method '{method.Method.Name}'.");
                }

                if (method.IsDefault && method.Attrib != null)
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' has both TokenParser and DefaultParser attributes.");
                }

                var parseletName = method.Method.Name;
                // this could be a default method so it may not have the TokenParser attribute
                if (method.Attrib != null && !Util.IsNullOrWhiteSpace(method.Attrib.Name))
                {
                    parseletName = method.Attrib.Name;
                }

                if (method.IsDefault)
                {
                    if (defaultParserMethod != null)
                    {
                        throw new RantInternalException(
                                  $"{GetType().Name}.ctor: Default parser method already defined: '{defaultParserMethod.Method.Name}'. " +
                                  $"Cannot define '{method.Method.Name}' as default parser method.");
                    }

                    // associate our default method with us
                    parseletNameDict.Add(parseletName, this);
                    defaultParserMethod = Delegate.CreateDelegate(typeof(TokenParserDelegate), this, method.Method) as TokenParserDelegate;
                    continue;
                }

                Parselet existingParselet;
                if (parseletNameDict.TryGetValue(parseletName, out existingParselet))
                {
                    throw new RantInternalException($"{GetType().Name}.ctor: '{existingParselet.GetType().Name}' already has an implementation called '{parseletName}'.");
                }

                // associate our method with us
                parseletNameDict.Add(parseletName, this);
                tokenParserMethods.Add(parseletName, Delegate.CreateDelegate(typeof(TokenParserDelegate), this, method.Method) as TokenParserDelegate);

                if (method.Attrib.TokenType != null)
                {
                    var type         = method.Attrib.TokenType.Value;
                    var existingName = "";
                    if (tokenTypeParseletNameDict.TryGetValue(type, out existingName))
                    {
                        throw new RantInternalException($"{GetType().Name}.ctor: '{existingName}' is already associated with R.{type}.");
                    }

                    // associate the method's name with the token type
                    tokenTypeParseletNameDict.Add(type, parseletName);
                }
            }
        }
Beispiel #3
0
        protected Parselet()
        {
            tokenParserMethods = new Dictionary<string, TokenParserDelegate>();

            parseletNames = new Stack<string>();
            tokens = new Stack<Token<R>>();
            outputDelegates = new Stack<Action<RantAction>>();

			// it doesn't matter if the methods are private, we can still call them because reflection
#if UNITY
			var methods =
				from method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
				let attrib = method.GetCustomAttributes(typeof(TokenParserAttribute), true).Cast<TokenParserAttribute>().FirstOrDefault()
				let defaultAttrib = method.GetCustomAttributes(typeof(DefaultParserAttribute), true).Cast<DefaultParserAttribute>().FirstOrDefault()
				where attrib != null || defaultAttrib != null
				select new { Method = method, Attrib = attrib, IsDefault = defaultAttrib != null };
#else
			var methods =
                from method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                let attrib = method.GetCustomAttribute<TokenParserAttribute>()
                let defaultAttrib = method.GetCustomAttribute<DefaultParserAttribute>()
                where attrib != null || defaultAttrib != null
                select new { Method = method, Attrib = attrib, IsDefault = defaultAttrib != null };
#endif


			if (!methods.Any())
                throw new RantInternalException($"{GetType().Name}.ctor: No parselet implementations found.");

            foreach (var method in methods)
            {
                if (method.Method.IsStatic)
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' musn't be static.");

                if (method.Method.IsGenericMethod)
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' musn't be generic:.");

                if (method.Method.GetParameters().Length != 1)
                    throw new RantInternalException($"{GetType().Name}.ctor: Invalid amount of parameters for parselet method '{method.Method.Name}'.");

                if (method.Method.GetParameters().First().ParameterType != typeof(Token<R>))
                    throw new RantInternalException($"{GetType().Name}.ctor: Wrong parameter type for parselet method '{method.Method.Name}'.");

                if (method.IsDefault && method.Attrib != null)
                    throw new RantInternalException($"{GetType().Name}.ctor: Parselet method '{method.Method.Name}' has both TokenParser and DefaultParser attributes.");

                var parseletName = method.Method.Name;
                // this could be a default method so it may not have the TokenParser attribute
                if (method.Attrib != null && !Util.IsNullOrWhiteSpace(method.Attrib.Name))
                    parseletName = method.Attrib.Name;

                if (method.IsDefault)
                {
                    if (defaultParserMethod != null)
                        throw new RantInternalException(
                            $"{GetType().Name}.ctor: Default parser method already defined: '{defaultParserMethod.Method.Name}'. " +
                            $"Cannot define '{method.Method.Name}' as default parser method.");

                    // associate our default method with us
                    parseletNameDict.Add(parseletName, this);
	                defaultParserMethod = Delegate.CreateDelegate(typeof(TokenParserDelegate), this, method.Method) as TokenParserDelegate;
                    continue;
                }

                Parselet existingParselet;
                if (parseletNameDict.TryGetValue(parseletName, out existingParselet))
                    throw new RantInternalException($"{GetType().Name}.ctor: '{existingParselet.GetType().Name}' already has an implementation called '{parseletName}'.");

                // associate our method with us
                parseletNameDict.Add(parseletName, this);
				tokenParserMethods.Add(parseletName, Delegate.CreateDelegate(typeof(TokenParserDelegate), this, method.Method) as TokenParserDelegate);

                if (method.Attrib.TokenType != null)
                {
                    var type = method.Attrib.TokenType.Value;
                    var existingName = "";
                    if (tokenTypeParseletNameDict.TryGetValue(type, out existingName))
                        throw new RantInternalException($"{GetType().Name}.ctor: '{existingName}' is already associated with R.{type}.");

                    // associate the method's name with the token type
                    tokenTypeParseletNameDict.Add(type, parseletName);
                }
            }
        }